diff --git a/.clang-format b/.clang-format index 0d03f70..a2683b8 100644 --- a/.clang-format +++ b/.clang-format @@ -1,4 +1,3 @@ ---- Language: Cpp # BasedOnStyle: LLVM # should be in line with IndentWidth @@ -13,8 +12,8 @@ AllowAllParametersOfDeclarationOnNextLine: true AllowShortBlocksOnASingleLine: false AllowShortCaseLabelsOnASingleLine: false AllowShortFunctionsOnASingleLine: All -AllowShortIfStatementsOnASingleLine: true -AllowShortLoopsOnASingleLine: true +AllowShortIfStatementsOnASingleLine: false +AllowShortLoopsOnASingleLine: false AlwaysBreakAfterDefinitionReturnType: None AlwaysBreakAfterReturnType: None AlwaysBreakBeforeMultilineStrings: false @@ -39,8 +38,8 @@ BreakBeforeTernaryOperators: true BreakConstructorInitializersBeforeComma: true BreakAfterJavaFieldAnnotations: false BreakStringLiterals: true -ColumnLimit: 120 -CommentPragmas: '^ IWYU pragma:' +ColumnLimit: 140 +CommentPragmas: '^( IWYU pragma:| @suppress)' ConstructorInitializerAllOnOneLineOrOnePerLine: false ConstructorInitializerIndentWidth: 0 ContinuationIndentWidth: 4 @@ -76,13 +75,13 @@ PenaltyBreakFirstLessLess: 120 PenaltyBreakString: 1000 PenaltyExcessCharacter: 1000000 PenaltyReturnTypeOnItsOwnLine: 60 -PointerAlignment: Right +PointerAlignment: Left ReflowComments: true SortIncludes: true SpaceAfterCStyleCast: false SpaceAfterTemplateKeyword: true SpaceBeforeAssignmentOperators: true -SpaceBeforeParens: ControlStatements +SpaceBeforeParens: Never SpaceInEmptyParentheses: false SpacesBeforeTrailingComments: 1 SpacesInAngles: false diff --git a/.gitignore b/.gitignore index d687e5f..7724009 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ .DS_Store /*.il +/.settings /avr-instr.html /blink.S /flash.* @@ -14,7 +15,6 @@ /*.ods /build*/ /*.logs -language.settings.xml /*.gtkw /Debug wo LLVM/ /*.txdb @@ -30,6 +30,5 @@ language.settings.xml /.gdbinit /*.out /dump.json -/src-gen/ /*.yaml /*.json diff --git a/.project b/.project index 84a8200..395ef36 100644 --- a/.project +++ b/.project @@ -23,6 +23,5 @@ org.eclipse.cdt.core.ccnature org.eclipse.cdt.managedbuilder.core.managedBuildNature org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - org.eclipse.linuxtools.tmf.project.nature diff --git a/.settings/org.eclipse.cdt.codan.core.prefs b/.settings/org.eclipse.cdt.codan.core.prefs deleted file mode 100644 index 067d6fd..0000000 --- a/.settings/org.eclipse.cdt.codan.core.prefs +++ /dev/null @@ -1,73 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.cdt.codan.checkers.errnoreturn=Warning -org.eclipse.cdt.codan.checkers.errnoreturn.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"No return\\")",implicit\=>false} -org.eclipse.cdt.codan.checkers.errreturnvalue=Error -org.eclipse.cdt.codan.checkers.errreturnvalue.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Unused return value\\")"} -org.eclipse.cdt.codan.checkers.nocommentinside=-Error -org.eclipse.cdt.codan.checkers.nocommentinside.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Nesting comments\\")"} -org.eclipse.cdt.codan.checkers.nolinecomment=-Error -org.eclipse.cdt.codan.checkers.nolinecomment.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Line comments\\")"} -org.eclipse.cdt.codan.checkers.noreturn=Error -org.eclipse.cdt.codan.checkers.noreturn.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"No return value\\")",implicit\=>false} -org.eclipse.cdt.codan.internal.checkers.AbstractClassCreation=Error -org.eclipse.cdt.codan.internal.checkers.AbstractClassCreation.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Abstract class cannot be instantiated\\")"} -org.eclipse.cdt.codan.internal.checkers.AmbiguousProblem=Error -org.eclipse.cdt.codan.internal.checkers.AmbiguousProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Ambiguous problem\\")"} -org.eclipse.cdt.codan.internal.checkers.AssignmentInConditionProblem=Warning -org.eclipse.cdt.codan.internal.checkers.AssignmentInConditionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Assignment in condition\\")"} -org.eclipse.cdt.codan.internal.checkers.AssignmentToItselfProblem=Error -org.eclipse.cdt.codan.internal.checkers.AssignmentToItselfProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Assignment to itself\\")"} -org.eclipse.cdt.codan.internal.checkers.CaseBreakProblem=Warning -org.eclipse.cdt.codan.internal.checkers.CaseBreakProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"No break at end of case\\")",no_break_comment\=>"no break",last_case_param\=>false,empty_case_param\=>false,enable_fallthrough_quickfix_param\=>false} -org.eclipse.cdt.codan.internal.checkers.CatchByReference=Warning -org.eclipse.cdt.codan.internal.checkers.CatchByReference.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Catching by reference is recommended\\")",unknown\=>false,exceptions\=>()} -org.eclipse.cdt.codan.internal.checkers.CircularReferenceProblem=Error -org.eclipse.cdt.codan.internal.checkers.CircularReferenceProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Circular inheritance\\")"} -org.eclipse.cdt.codan.internal.checkers.ClassMembersInitialization=Warning -org.eclipse.cdt.codan.internal.checkers.ClassMembersInitialization.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Class members should be properly initialized\\")",skip\=>true} -org.eclipse.cdt.codan.internal.checkers.DecltypeAutoProblem=Error -org.eclipse.cdt.codan.internal.checkers.DecltypeAutoProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid 'decltype(auto)' specifier\\")"} -org.eclipse.cdt.codan.internal.checkers.FieldResolutionProblem=Error -org.eclipse.cdt.codan.internal.checkers.FieldResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Field cannot be resolved\\")"} -org.eclipse.cdt.codan.internal.checkers.FunctionResolutionProblem=Error -org.eclipse.cdt.codan.internal.checkers.FunctionResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Function cannot be resolved\\")"} -org.eclipse.cdt.codan.internal.checkers.InvalidArguments=Error -org.eclipse.cdt.codan.internal.checkers.InvalidArguments.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid arguments\\")"} -org.eclipse.cdt.codan.internal.checkers.InvalidTemplateArgumentsProblem=Error -org.eclipse.cdt.codan.internal.checkers.InvalidTemplateArgumentsProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid template argument\\")"} -org.eclipse.cdt.codan.internal.checkers.LabelStatementNotFoundProblem=Error -org.eclipse.cdt.codan.internal.checkers.LabelStatementNotFoundProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Label statement not found\\")"} -org.eclipse.cdt.codan.internal.checkers.MemberDeclarationNotFoundProblem=Error -org.eclipse.cdt.codan.internal.checkers.MemberDeclarationNotFoundProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Member declaration not found\\")"} -org.eclipse.cdt.codan.internal.checkers.MethodResolutionProblem=Error -org.eclipse.cdt.codan.internal.checkers.MethodResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Method cannot be resolved\\")"} -org.eclipse.cdt.codan.internal.checkers.NamingConventionFunctionChecker=-Info -org.eclipse.cdt.codan.internal.checkers.NamingConventionFunctionChecker.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Name convention for function\\")",pattern\=>"^[a-z]",macro\=>true,exceptions\=>()} -org.eclipse.cdt.codan.internal.checkers.NonVirtualDestructorProblem=Warning -org.eclipse.cdt.codan.internal.checkers.NonVirtualDestructorProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Class has a virtual method and non-virtual destructor\\")"} -org.eclipse.cdt.codan.internal.checkers.OverloadProblem=Error -org.eclipse.cdt.codan.internal.checkers.OverloadProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid overload\\")"} -org.eclipse.cdt.codan.internal.checkers.RedeclarationProblem=Error -org.eclipse.cdt.codan.internal.checkers.RedeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid redeclaration\\")"} -org.eclipse.cdt.codan.internal.checkers.RedefinitionProblem=Error -org.eclipse.cdt.codan.internal.checkers.RedefinitionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid redefinition\\")"} -org.eclipse.cdt.codan.internal.checkers.ReturnStyleProblem=-Warning -org.eclipse.cdt.codan.internal.checkers.ReturnStyleProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Return with parenthesis\\")"} -org.eclipse.cdt.codan.internal.checkers.ScanfFormatStringSecurityProblem=-Warning -org.eclipse.cdt.codan.internal.checkers.ScanfFormatStringSecurityProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Format String Vulnerability\\")"} -org.eclipse.cdt.codan.internal.checkers.StatementHasNoEffectProblem=Warning -org.eclipse.cdt.codan.internal.checkers.StatementHasNoEffectProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Statement has no effect\\")",macro\=>true,exceptions\=>()} -org.eclipse.cdt.codan.internal.checkers.SuggestedParenthesisProblem=Warning -org.eclipse.cdt.codan.internal.checkers.SuggestedParenthesisProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Suggested parenthesis around expression\\")",paramNot\=>false} -org.eclipse.cdt.codan.internal.checkers.SuspiciousSemicolonProblem=Warning -org.eclipse.cdt.codan.internal.checkers.SuspiciousSemicolonProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Suspicious semicolon\\")",else\=>false,afterelse\=>false} -org.eclipse.cdt.codan.internal.checkers.TypeResolutionProblem=Error -org.eclipse.cdt.codan.internal.checkers.TypeResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Type cannot be resolved\\")"} -org.eclipse.cdt.codan.internal.checkers.UnusedFunctionDeclarationProblem=Warning -org.eclipse.cdt.codan.internal.checkers.UnusedFunctionDeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Unused function declaration\\")",macro\=>true} -org.eclipse.cdt.codan.internal.checkers.UnusedStaticFunctionProblem=Warning -org.eclipse.cdt.codan.internal.checkers.UnusedStaticFunctionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Unused static function\\")",macro\=>true} -org.eclipse.cdt.codan.internal.checkers.UnusedVariableDeclarationProblem=Warning -org.eclipse.cdt.codan.internal.checkers.UnusedVariableDeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Unused variable declaration in file scope\\")",macro\=>true,exceptions\=>("@(\#)","$Id")} -org.eclipse.cdt.codan.internal.checkers.VariableResolutionProblem=Error -org.eclipse.cdt.codan.internal.checkers.VariableResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Symbol is not resolved\\")"} diff --git a/.settings/org.eclipse.cdt.core.prefs b/.settings/org.eclipse.cdt.core.prefs deleted file mode 100644 index 7982989..0000000 --- a/.settings/org.eclipse.cdt.core.prefs +++ /dev/null @@ -1,13 +0,0 @@ -eclipse.preferences.version=1 -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.1259602404/LLVM_HOME/delimiter=\: -environment/project/cdt.managedbuild.config.gnu.exe.release.1745230171.1259602404/LLVM_HOME/operation=append -environment/project/cdt.managedbuild.config.gnu.exe.release.1745230171.1259602404/LLVM_HOME/value=/usr/lib/llvm-6.0 -environment/project/cdt.managedbuild.config.gnu.exe.release.1745230171.1259602404/append=true -environment/project/cdt.managedbuild.config.gnu.exe.release.1745230171.1259602404/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 diff --git a/.settings/org.eclipse.cdt.managedbuilder.core.prefs b/.settings/org.eclipse.cdt.managedbuilder.core.prefs deleted file mode 100644 index f299fce..0000000 --- a/.settings/org.eclipse.cdt.managedbuilder.core.prefs +++ /dev/null @@ -1,37 +0,0 @@ -eclipse.preferences.version=1 -environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.debug.1751741082/CPATH/delimiter=\: -environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.debug.1751741082/CPATH/operation=remove -environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.debug.1751741082/CPLUS_INCLUDE_PATH/delimiter=\: -environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.debug.1751741082/CPLUS_INCLUDE_PATH/operation=remove -environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.debug.1751741082/C_INCLUDE_PATH/delimiter=\: -environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.debug.1751741082/C_INCLUDE_PATH/operation=remove -environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.debug.1751741082/append=true -environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.debug.1751741082/appendContributed=true -environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.release.1745230171.1259602404/CPATH/delimiter=\: -environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.release.1745230171.1259602404/CPATH/operation=remove -environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.release.1745230171.1259602404/CPLUS_INCLUDE_PATH/delimiter=\: -environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.release.1745230171.1259602404/CPLUS_INCLUDE_PATH/operation=remove -environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.release.1745230171.1259602404/C_INCLUDE_PATH/delimiter=\: -environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.release.1745230171.1259602404/C_INCLUDE_PATH/operation=remove -environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.release.1745230171.1259602404/append=true -environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.release.1745230171.1259602404/appendContributed=true -environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.release.1745230171/CPATH/delimiter=\: -environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.release.1745230171/CPATH/operation=remove -environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.release.1745230171/CPLUS_INCLUDE_PATH/delimiter=\: -environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.release.1745230171/CPLUS_INCLUDE_PATH/operation=remove -environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.release.1745230171/C_INCLUDE_PATH/delimiter=\: -environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.release.1745230171/C_INCLUDE_PATH/operation=remove -environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.release.1745230171/append=true -environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.release.1745230171/appendContributed=true -environment/buildEnvironmentLibrary/cdt.managedbuild.config.gnu.exe.debug.1751741082/LIBRARY_PATH/delimiter=\: -environment/buildEnvironmentLibrary/cdt.managedbuild.config.gnu.exe.debug.1751741082/LIBRARY_PATH/operation=remove -environment/buildEnvironmentLibrary/cdt.managedbuild.config.gnu.exe.debug.1751741082/append=true -environment/buildEnvironmentLibrary/cdt.managedbuild.config.gnu.exe.debug.1751741082/appendContributed=true -environment/buildEnvironmentLibrary/cdt.managedbuild.config.gnu.exe.release.1745230171.1259602404/LIBRARY_PATH/delimiter=\: -environment/buildEnvironmentLibrary/cdt.managedbuild.config.gnu.exe.release.1745230171.1259602404/LIBRARY_PATH/operation=remove -environment/buildEnvironmentLibrary/cdt.managedbuild.config.gnu.exe.release.1745230171.1259602404/append=true -environment/buildEnvironmentLibrary/cdt.managedbuild.config.gnu.exe.release.1745230171.1259602404/appendContributed=true -environment/buildEnvironmentLibrary/cdt.managedbuild.config.gnu.exe.release.1745230171/LIBRARY_PATH/delimiter=\: -environment/buildEnvironmentLibrary/cdt.managedbuild.config.gnu.exe.release.1745230171/LIBRARY_PATH/operation=remove -environment/buildEnvironmentLibrary/cdt.managedbuild.config.gnu.exe.release.1745230171/append=true -environment/buildEnvironmentLibrary/cdt.managedbuild.config.gnu.exe.release.1745230171/appendContributed=true diff --git a/CMakeLists.txt b/CMakeLists.txt index 28ba1da..3070844 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,92 +1,106 @@ cmake_minimum_required(VERSION 3.12) +list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake) ############################################################################### # ############################################################################### project(dbt-rise-tgc VERSION 1.0.0) include(GNUInstallDirs) +include(flink) find_package(elfio QUIET) -find_package(Boost COMPONENTS coroutine) - -if(WITH_LLVM) - if(DEFINED ENV{LLVM_HOME}) - find_path (LLVM_DIR LLVM-Config.cmake $ENV{LLVM_HOME}/lib/cmake/llvm) - endif(DEFINED ENV{LLVM_HOME}) - find_package(LLVM REQUIRED CONFIG) - message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}") - message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}") - llvm_map_components_to_libnames(llvm_libs support core mcjit x86codegen x86asmparser) -endif() - -#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) +find_package(jsoncpp) +find_package(Boost COMPONENTS coroutine REQUIRED) add_subdirectory(softfloat) -# library files -FILE(GLOB TGC_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/iss/*.cpp) -FILE(GLOB TGC_VM_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/vm/interp/vm_*.cpp) - set(LIB_SOURCES - src/vm/fp_functions.cpp - src/plugin/instruction_count.cpp - - ${TGC_SOURCES} - ${TGC_VM_SOURCES} + src/iss/plugin/instruction_count.cpp + src/iss/arch/tgc5c.cpp + src/vm/interp/vm_tgc5c.cpp + src/vm/fp_functions.cpp ) -if(TARGET RapidJSON) - list(APPEND LIB_SOURCES src/plugin/cycle_estimate.cpp src/plugin/pctrace.cpp) +if(WITH_TCC) + list(APPEND LIB_SOURCES + src/vm/tcc/vm_tgc5c.cpp + ) endif() +if(WITH_LLVM) + list(APPEND LIB_SOURCES + src/vm/llvm/vm_tgc5c.cpp + src/vm/llvm/fp_impl.cpp + ) +endif() +if(WITH_ASMJIT) + list(APPEND LIB_SOURCES + src/vm/asmjit/vm_tgc5c.cpp + ) +endif() +# library files +FILE(GLOB GEN_ISS_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src-gen/iss/arch/*.cpp) +FILE(GLOB GEN_VM_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src-gen/vm/interp/vm_*.cpp) +FILE(GLOB GEN_YAML_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/contrib/instr/*.yaml) +list(APPEND LIB_SOURCES ${GEN_ISS_SOURCES} ${GEN_VM_SOURCES}) +foreach(FILEPATH ${GEN_ISS_SOURCES}) + get_filename_component(CORE ${FILEPATH} NAME_WE) + string(TOUPPER ${CORE} CORE) + list(APPEND LIB_DEFINES CORE_${CORE}) +endforeach() +message(STATUS "Core defines are ${LIB_DEFINES}") if(WITH_LLVM) - FILE(GLOB TGC_LLVM_SOURCES - ${CMAKE_CURRENT_SOURCE_DIR}/src/vm/llvm/vm_*.cpp - ) - list(APPEND LIB_SOURCES ${TGC_LLVM_SOURCES}) + FILE(GLOB LLVM_GEN_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src-gen/vm/llvm/vm_*.cpp) + list(APPEND LIB_SOURCES ${LLVM_GEN_SOURCES}) endif() if(WITH_TCC) - FILE(GLOB TGC_TCC_SOURCES - ${CMAKE_CURRENT_SOURCE_DIR}/src/vm/tcc/vm_*.cpp - ) - list(APPEND LIB_SOURCES ${TGC_TCC_SOURCES}) + FILE(GLOB TCC_GEN_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src-gen/vm/tcc/vm_*.cpp) + list(APPEND LIB_SOURCES ${TCC_GEN_SOURCES}) +endif() +if(WITH_ASMJIT) + FILE(GLOB TCC_GEN_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src-gen/vm/asmjit/vm_*.cpp) + list(APPEND LIB_SOURCES ${TCC_GEN_SOURCES}) +endif() +if(TARGET yaml-cpp::yaml-cpp) + list(APPEND LIB_SOURCES + src/iss/plugin/cycle_estimate.cpp + src/iss/plugin/instruction_count.cpp + ) endif() - # Define the library -add_library(${PROJECT_NAME} ${LIB_SOURCES}) -# list code gen dependencies -if(TARGET ${CORE_NAME}_cpp) - add_dependencies(${PROJECT_NAME} ${CORE_NAME}_cpp) -endif() +add_library(${PROJECT_NAME} SHARED ${LIB_SOURCES}) if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") - target_compile_options(${PROJECT_NAME} PRIVATE -Wno-shift-count-overflow) + target_compile_options(${PROJECT_NAME} PRIVATE -Wno-shift-count-overflow) elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") target_compile_options(${PROJECT_NAME} PRIVATE /wd4293) endif() -target_include_directories(${PROJECT_NAME} PUBLIC incl) -target_link_libraries(${PROJECT_NAME} PUBLIC softfloat scc-util jsoncpp Boost::coroutine) -if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") - target_link_libraries(${PROJECT_NAME} PUBLIC -Wl,--whole-archive dbt-rise-core -Wl,--no-whole-archive) -else() - target_link_libraries(${PROJECT_NAME} PUBLIC dbt-rise-core) -endif() -if(TARGET CONAN_PKG::elfio) - target_link_libraries(${PROJECT_NAME} PUBLIC CONAN_PKG::elfio) -elseif(TARGET elfio::elfio) - target_link_libraries(${PROJECT_NAME} PUBLIC elfio::elfio) -else() - message(FATAL_ERROR "No elfio library found, maybe a find_package() call is missing") -endif() -if(TARGET RapidJSON) - target_link_libraries(${PROJECT_NAME} PUBLIC RapidJSON) +target_include_directories(${PROJECT_NAME} PUBLIC src) +target_include_directories(${PROJECT_NAME} PUBLIC src-gen) + +target_force_link_libraries(${PROJECT_NAME} PRIVATE dbt-rise-core) +# only re-export the include paths +get_target_property(DBT_CORE_INCL dbt-rise-core INTERFACE_INCLUDE_DIRECTORIES) +target_include_directories(${PROJECT_NAME} INTERFACE ${DBT_CORE_INCL}) +get_target_property(DBT_CORE_DEFS dbt-rise-core INTERFACE_COMPILE_DEFINITIONS) +if(NOT (DBT_CORE_DEFS STREQUAL DBT_CORE_DEFS-NOTFOUND)) + target_compile_definitions(${PROJECT_NAME} INTERFACE ${DBT_CORE_DEFS}) endif() +target_link_libraries(${PROJECT_NAME} PUBLIC elfio::elfio softfloat scc-util Boost::coroutine) +if(TARGET yaml-cpp::yaml-cpp) + target_compile_definitions(${PROJECT_NAME} PUBLIC WITH_PLUGINS) + target_link_libraries(${PROJECT_NAME} PUBLIC yaml-cpp::yaml-cpp) +endif() + +if(WITH_LLVM) + find_package(LLVM) + target_compile_definitions(${PROJECT_NAME} PUBLIC ${LLVM_DEFINITIONS}) + target_include_directories(${PROJECT_NAME} PUBLIC ${LLVM_INCLUDE_DIRS}) + if(BUILD_SHARED_LIBS) + target_link_libraries( ${PROJECT_NAME} PUBLIC ${LLVM_LIBRARIES}) + endif() +endif() set_target_properties(${PROJECT_NAME} PROPERTIES VERSION ${PROJECT_VERSION} @@ -106,25 +120,43 @@ install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/incl/iss COMPONENT ${PROJECT_NAME} FILES_MATCHING # install only matched files PATTERN "*.h" # select header files ) +install(FILES ${GEN_YAML_SOURCES} DESTINATION share/tgc-vp) ############################################################################### # ############################################################################### +set(CMAKE_INSTALL_RPATH $ORIGIN/../${CMAKE_INSTALL_LIBDIR}) project(tgc-sim) find_package(Boost COMPONENTS program_options thread REQUIRED) add_executable(${PROJECT_NAME} src/main.cpp) +if(TARGET ${CORE_NAME}_cpp) + list(APPEND TGC_SOURCES ${${CORE_NAME}_OUTPUT_FILES}) +else() + FILE(GLOB TGC_SOURCES + ${CMAKE_CURRENT_SOURCE_DIR}/src-gen/iss/arch/*.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src-gen/vm/interp/vm_*.cpp + ) + list(APPEND TGC_SOURCES ${GEN_SOURCES}) +endif() + foreach(F IN LISTS TGC_SOURCES) - string(REGEX REPLACE ".*/([^/]*)\.cpp" "\\1" CORE_NAME_LC ${F}) - string(TOUPPER ${CORE_NAME_LC} CORE_NAME) - target_compile_definitions(${PROJECT_NAME} PRIVATE CORE_${CORE_NAME}) + if (${F} MATCHES ".*/arch/([^/]*)\.cpp") + string(REGEX REPLACE ".*/([^/]*)\.cpp" "\\1" CORE_NAME_LC ${F}) + string(TOUPPER ${CORE_NAME_LC} CORE_NAME) + target_compile_definitions(${PROJECT_NAME} PRIVATE CORE_${CORE_NAME}) + endif() endforeach() -if(WITH_LLVM) - target_compile_definitions(${PROJECT_NAME} PRIVATE WITH_LLVM) - target_link_libraries(${PROJECT_NAME} PUBLIC ${llvm_libs}) -endif() -# Links the target exe against the libraries -target_link_libraries(${PROJECT_NAME} PUBLIC dbt-rise-tgc) +#if(WITH_LLVM) +# target_compile_definitions(${PROJECT_NAME} PRIVATE WITH_LLVM) +# #target_link_libraries(${PROJECT_NAME} PUBLIC ${llvm_libs}) +#endif() +#if(WITH_TCC) +# target_compile_definitions(${PROJECT_NAME} PRIVATE WITH_TCC) +#endif() + +target_link_libraries(${PROJECT_NAME} PUBLIC dbt-rise-tgc fmt::fmt) + if(TARGET Boost::program_options) target_link_libraries(${PROJECT_NAME} PUBLIC Boost::program_options) else() @@ -144,27 +176,51 @@ install(TARGETS tgc-sim PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME} # headers for mac (note the different component -> different package) INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} # headers ) + +if(BUILD_TESTING) + # ... CMake code to create tests ... + add_test(NAME tgc-sim-interp + COMMAND tgc-sim -f ${CMAKE_BINARY_DIR}/../../Firmwares/hello-world/hello --backend interp) + if(WITH_TCC) + add_test(NAME tgc-sim-tcc + COMMAND tgc-sim -f ${CMAKE_BINARY_DIR}/../../Firmwares/hello-world/hello --backend tcc) + endif() + if(WITH_LLVM) + add_test(NAME tgc-sim-llvm + COMMAND tgc-sim -f ${CMAKE_BINARY_DIR}/../../Firmwares/hello-world/hello --backend llvm) + endif() + if(WITH_ASMJIT) + add_test(NAME tgc-sim-asmjit + COMMAND tgc-sim -f ${CMAKE_BINARY_DIR}/../../Firmwares/hello-world/hello --backend asmjit) + endif() +endif() ############################################################################### # ############################################################################### -project(dbt-rise-tgc_sc VERSION 1.0.0) - -include(SystemCPackage) -if(SystemC_FOUND) - add_library(${PROJECT_NAME} src/sysc/core_complex.cpp) +if(TARGET scc-sysc) + project(dbt-rise-tgc_sc VERSION 1.0.0) + set(LIB_SOURCES + src/sysc/core_complex.cpp + src/sysc/register_tgc_c.cpp + ) + FILE(GLOB GEN_SC_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src-gen/sysc/register_*.cpp) + list(APPEND LIB_SOURCES ${GEN_SC_SOURCES}) + add_library(${PROJECT_NAME} ${LIB_SOURCES}) target_compile_definitions(${PROJECT_NAME} PUBLIC WITH_SYSTEMC) target_compile_definitions(${PROJECT_NAME} PRIVATE CORE_${CORE_NAME}) foreach(F IN LISTS TGC_SOURCES) - string(REGEX REPLACE ".*/([^/]*)\.cpp" "\\1" CORE_NAME_LC ${F}) - string(TOUPPER ${CORE_NAME_LC} CORE_NAME) - target_compile_definitions(${PROJECT_NAME} PRIVATE CORE_${CORE_NAME}) + if (${F} MATCHES ".*/arch/([^/]*)\.cpp") + string(REGEX REPLACE ".*/([^/]*)\.cpp" "\\1" CORE_NAME_LC ${F}) + string(TOUPPER ${CORE_NAME_LC} CORE_NAME) + target_compile_definitions(${PROJECT_NAME} PRIVATE CORE_${CORE_NAME}) + endif() endforeach() - target_link_libraries(${PROJECT_NAME} PUBLIC dbt-rise-tgc scc) - if(WITH_LLVM) - target_link_libraries(${PROJECT_NAME} PUBLIC ${llvm_libs}) - endif() + target_link_libraries(${PROJECT_NAME} PUBLIC dbt-rise-tgc scc-sysc) +# if(WITH_LLVM) +# target_link_libraries(${PROJECT_NAME} PUBLIC ${llvm_libs}) +# endif() - set(LIB_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/incl/sysc/core_complex.h) + set(LIB_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/src/sysc/core_complex.h) set_target_properties(${PROJECT_NAME} PROPERTIES VERSION ${PROJECT_VERSION} FRAMEWORK FALSE diff --git a/cmake/flink.cmake b/cmake/flink.cmake new file mode 100644 index 0000000..69b5c9f --- /dev/null +++ b/cmake/flink.cmake @@ -0,0 +1,35 @@ +# according to https://github.com/horance-liu/flink.cmake/tree/master +# SPDX-License-Identifier: Apache-2.0 + +include(CMakeParseArguments) + +function(target_do_force_link_libraries target visibility lib) + if(MSVC) + target_link_libraries(${target} ${visibility} "/WHOLEARCHIVE:${lib}") + elseif(APPLE) + target_link_libraries(${target} ${visibility} -Wl,-force_load ${lib}) + else() + target_link_libraries(${target} ${visibility} -Wl,--whole-archive ${lib} -Wl,--no-whole-archive) + endif() +endfunction() + +function(target_force_link_libraries target) + cmake_parse_arguments(FLINK + "" + "" + "PUBLIC;INTERFACE;PRIVATE" + ${ARGN} + ) + + foreach(lib IN LISTS FLINK_PUBLIC) + target_do_force_link_libraries(${target} PUBLIC ${lib}) + endforeach() + + foreach(lib IN LISTS FLINK_INTERFACE) + target_do_force_link_libraries(${target} INTERFACE ${lib}) + endforeach() + + foreach(lib IN LISTS FLINK_PRIVATE) + target_do_force_link_libraries(${target} PRIVATE ${lib}) + endforeach() +endfunction() \ No newline at end of file diff --git a/contrib/instr/.gitignore b/contrib/instr/.gitignore new file mode 100644 index 0000000..88b59f2 --- /dev/null +++ b/contrib/instr/.gitignore @@ -0,0 +1 @@ +/*.yaml \ No newline at end of file diff --git a/contrib/instr/TGC5C_instr.yaml b/contrib/instr/TGC5C_instr.yaml new file mode 100644 index 0000000..c1692e0 --- /dev/null +++ b/contrib/instr/TGC5C_instr.yaml @@ -0,0 +1,624 @@ + +RVI: + LUI: + index: 0 + encoding: 0b00000000000000000000000000110111 + mask: 0b00000000000000000000000001111111 + size: 32 + branch: false + delay: 1 + AUIPC: + index: 1 + encoding: 0b00000000000000000000000000010111 + mask: 0b00000000000000000000000001111111 + size: 32 + branch: false + delay: 1 + JAL: + index: 2 + encoding: 0b00000000000000000000000001101111 + mask: 0b00000000000000000000000001111111 + size: 32 + branch: true + delay: 1 + JALR: + index: 3 + encoding: 0b00000000000000000000000001100111 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: true + delay: [1,1] + BEQ: + index: 4 + encoding: 0b00000000000000000000000001100011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: true + delay: [1,1] + BNE: + index: 5 + encoding: 0b00000000000000000001000001100011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: true + delay: [1,1] + BLT: + index: 6 + encoding: 0b00000000000000000100000001100011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: true + delay: [1,1] + BGE: + index: 7 + encoding: 0b00000000000000000101000001100011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: true + delay: [1,1] + BLTU: + index: 8 + encoding: 0b00000000000000000110000001100011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: true + delay: [1,1] + BGEU: + index: 9 + encoding: 0b00000000000000000111000001100011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: true + delay: [1,1] + LB: + index: 10 + encoding: 0b00000000000000000000000000000011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: false + delay: 1 + LH: + index: 11 + encoding: 0b00000000000000000001000000000011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: false + delay: 1 + LW: + index: 12 + encoding: 0b00000000000000000010000000000011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: false + delay: 1 + LBU: + index: 13 + encoding: 0b00000000000000000100000000000011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: false + delay: 1 + LHU: + index: 14 + encoding: 0b00000000000000000101000000000011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: false + delay: 1 + SB: + index: 15 + encoding: 0b00000000000000000000000000100011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: false + delay: 1 + SH: + index: 16 + encoding: 0b00000000000000000001000000100011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: false + delay: 1 + SW: + index: 17 + encoding: 0b00000000000000000010000000100011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: false + delay: 1 + ADDI: + index: 18 + encoding: 0b00000000000000000000000000010011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: false + delay: 1 + SLTI: + index: 19 + encoding: 0b00000000000000000010000000010011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: false + delay: 1 + SLTIU: + index: 20 + encoding: 0b00000000000000000011000000010011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: false + delay: 1 + XORI: + index: 21 + encoding: 0b00000000000000000100000000010011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: false + delay: 1 + ORI: + index: 22 + encoding: 0b00000000000000000110000000010011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: false + delay: 1 + ANDI: + index: 23 + encoding: 0b00000000000000000111000000010011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: false + delay: 1 + SLLI: + index: 24 + encoding: 0b00000000000000000001000000010011 + mask: 0b11111110000000000111000001111111 + size: 32 + branch: false + delay: 1 + SRLI: + index: 25 + encoding: 0b00000000000000000101000000010011 + mask: 0b11111110000000000111000001111111 + size: 32 + branch: false + delay: 1 + SRAI: + index: 26 + encoding: 0b01000000000000000101000000010011 + mask: 0b11111110000000000111000001111111 + size: 32 + branch: false + delay: 1 + ADD: + index: 27 + encoding: 0b00000000000000000000000000110011 + mask: 0b11111110000000000111000001111111 + size: 32 + branch: false + delay: 1 + SUB: + index: 28 + encoding: 0b01000000000000000000000000110011 + mask: 0b11111110000000000111000001111111 + size: 32 + branch: false + delay: 1 + SLL: + index: 29 + encoding: 0b00000000000000000001000000110011 + mask: 0b11111110000000000111000001111111 + size: 32 + branch: false + delay: 1 + SLT: + index: 30 + encoding: 0b00000000000000000010000000110011 + mask: 0b11111110000000000111000001111111 + size: 32 + branch: false + delay: 1 + SLTU: + index: 31 + encoding: 0b00000000000000000011000000110011 + mask: 0b11111110000000000111000001111111 + size: 32 + branch: false + delay: 1 + XOR: + index: 32 + encoding: 0b00000000000000000100000000110011 + mask: 0b11111110000000000111000001111111 + size: 32 + branch: false + delay: 1 + SRL: + index: 33 + encoding: 0b00000000000000000101000000110011 + mask: 0b11111110000000000111000001111111 + size: 32 + branch: false + delay: 1 + SRA: + index: 34 + encoding: 0b01000000000000000101000000110011 + mask: 0b11111110000000000111000001111111 + size: 32 + branch: false + delay: 1 + OR: + index: 35 + encoding: 0b00000000000000000110000000110011 + mask: 0b11111110000000000111000001111111 + size: 32 + branch: false + delay: 1 + AND: + index: 36 + encoding: 0b00000000000000000111000000110011 + mask: 0b11111110000000000111000001111111 + size: 32 + branch: false + delay: 1 + FENCE: + index: 37 + encoding: 0b00000000000000000000000000001111 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: false + delay: 1 + ECALL: + index: 38 + encoding: 0b00000000000000000000000001110011 + mask: 0b11111111111111111111111111111111 + attributes: [[name:no_cont]] + size: 32 + branch: false + delay: 1 + EBREAK: + index: 39 + encoding: 0b00000000000100000000000001110011 + mask: 0b11111111111111111111111111111111 + attributes: [[name:no_cont]] + size: 32 + branch: false + delay: 1 + MRET: + index: 40 + encoding: 0b00110000001000000000000001110011 + mask: 0b11111111111111111111111111111111 + attributes: [[name:no_cont]] + size: 32 + branch: false + delay: 1 + WFI: + index: 41 + encoding: 0b00010000010100000000000001110011 + mask: 0b11111111111111111111111111111111 + size: 32 + branch: false + delay: 1 +Zicsr: + CSRRW: + index: 42 + encoding: 0b00000000000000000001000001110011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: false + delay: 1 + CSRRS: + index: 43 + encoding: 0b00000000000000000010000001110011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: false + delay: 1 + CSRRC: + index: 44 + encoding: 0b00000000000000000011000001110011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: false + delay: 1 + CSRRWI: + index: 45 + encoding: 0b00000000000000000101000001110011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: false + delay: 1 + CSRRSI: + index: 46 + encoding: 0b00000000000000000110000001110011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: false + delay: 1 + CSRRCI: + index: 47 + encoding: 0b00000000000000000111000001110011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: false + delay: 1 +Zifencei: + FENCE_I: + index: 48 + encoding: 0b00000000000000000001000000001111 + mask: 0b00000000000000000111000001111111 + attributes: [[name:flush]] + size: 32 + branch: false + delay: 1 +RV32M: + MUL: + index: 49 + encoding: 0b00000010000000000000000000110011 + mask: 0b11111110000000000111000001111111 + size: 32 + branch: false + delay: 1 + MULH: + index: 50 + encoding: 0b00000010000000000001000000110011 + mask: 0b11111110000000000111000001111111 + size: 32 + branch: false + delay: 1 + MULHSU: + index: 51 + encoding: 0b00000010000000000010000000110011 + mask: 0b11111110000000000111000001111111 + size: 32 + branch: false + delay: 1 + MULHU: + index: 52 + encoding: 0b00000010000000000011000000110011 + mask: 0b11111110000000000111000001111111 + size: 32 + branch: false + delay: 1 + DIV: + index: 53 + encoding: 0b00000010000000000100000000110011 + mask: 0b11111110000000000111000001111111 + size: 32 + branch: false + delay: 1 + DIVU: + index: 54 + encoding: 0b00000010000000000101000000110011 + mask: 0b11111110000000000111000001111111 + size: 32 + branch: false + delay: 1 + REM: + index: 55 + encoding: 0b00000010000000000110000000110011 + mask: 0b11111110000000000111000001111111 + size: 32 + branch: false + delay: 1 + REMU: + index: 56 + encoding: 0b00000010000000000111000000110011 + mask: 0b11111110000000000111000001111111 + size: 32 + branch: false + delay: 1 +Zca: + C__ADDI4SPN: + index: 57 + encoding: 0b0000000000000000 + mask: 0b1110000000000011 + size: 16 + branch: false + delay: 1 + C__LW: + index: 58 + encoding: 0b0100000000000000 + mask: 0b1110000000000011 + size: 16 + branch: false + delay: 1 + C__SW: + index: 59 + encoding: 0b1100000000000000 + mask: 0b1110000000000011 + size: 16 + branch: false + delay: 1 + C__ADDI: + index: 60 + encoding: 0b0000000000000001 + mask: 0b1110000000000011 + size: 16 + branch: false + delay: 1 + C__NOP: + index: 61 + encoding: 0b0000000000000001 + mask: 0b1110111110000011 + size: 16 + branch: false + delay: 1 + C__JAL: + index: 62 + encoding: 0b0010000000000001 + mask: 0b1110000000000011 + attributes: [[name:enable, value:1]] + size: 16 + branch: true + delay: 1 + C__LI: + index: 63 + encoding: 0b0100000000000001 + mask: 0b1110000000000011 + size: 16 + branch: false + delay: 1 + C__LUI: + index: 64 + encoding: 0b0110000000000001 + mask: 0b1110000000000011 + size: 16 + branch: false + delay: 1 + C__ADDI16SP: + index: 65 + encoding: 0b0110000100000001 + mask: 0b1110111110000011 + size: 16 + branch: false + delay: 1 + __reserved_clui: + index: 66 + encoding: 0b0110000000000001 + mask: 0b1111000001111111 + size: 16 + branch: false + delay: 1 + C__SRLI: + index: 67 + encoding: 0b1000000000000001 + mask: 0b1111110000000011 + attributes: [[name:enable, value:1]] + size: 16 + branch: false + delay: 1 + C__SRAI: + index: 68 + encoding: 0b1000010000000001 + mask: 0b1111110000000011 + attributes: [[name:enable, value:1]] + size: 16 + branch: false + delay: 1 + C__ANDI: + index: 69 + encoding: 0b1000100000000001 + mask: 0b1110110000000011 + size: 16 + branch: false + delay: 1 + C__SUB: + index: 70 + encoding: 0b1000110000000001 + mask: 0b1111110001100011 + size: 16 + branch: false + delay: 1 + C__XOR: + index: 71 + encoding: 0b1000110000100001 + mask: 0b1111110001100011 + size: 16 + branch: false + delay: 1 + C__OR: + index: 72 + encoding: 0b1000110001000001 + mask: 0b1111110001100011 + size: 16 + branch: false + delay: 1 + C__AND: + index: 73 + encoding: 0b1000110001100001 + mask: 0b1111110001100011 + size: 16 + branch: false + delay: 1 + C__J: + index: 74 + encoding: 0b1010000000000001 + mask: 0b1110000000000011 + size: 16 + branch: true + delay: 1 + C__BEQZ: + index: 75 + encoding: 0b1100000000000001 + mask: 0b1110000000000011 + size: 16 + branch: true + delay: [1,1] + C__BNEZ: + index: 76 + encoding: 0b1110000000000001 + mask: 0b1110000000000011 + size: 16 + branch: true + delay: [1,1] + C__SLLI: + index: 77 + encoding: 0b0000000000000010 + mask: 0b1111000000000011 + attributes: [[name:enable, value:1]] + size: 16 + branch: false + delay: 1 + C__LWSP: + index: 78 + encoding: 0b0100000000000010 + mask: 0b1110000000000011 + size: 16 + branch: false + delay: 1 + C__MV: + index: 79 + encoding: 0b1000000000000010 + mask: 0b1111000000000011 + size: 16 + branch: false + delay: 1 + C__JR: + index: 80 + encoding: 0b1000000000000010 + mask: 0b1111000001111111 + size: 16 + branch: true + delay: 1 + __reserved_cmv: + index: 81 + encoding: 0b1000000000000010 + mask: 0b1111111111111111 + size: 16 + branch: false + delay: 1 + C__ADD: + index: 82 + encoding: 0b1001000000000010 + mask: 0b1111000000000011 + size: 16 + branch: false + delay: 1 + C__JALR: + index: 83 + encoding: 0b1001000000000010 + mask: 0b1111000001111111 + size: 16 + branch: true + delay: 1 + C__EBREAK: + index: 84 + encoding: 0b1001000000000010 + mask: 0b1111111111111111 + size: 16 + branch: false + delay: 1 + C__SWSP: + index: 85 + encoding: 0b1100000000000010 + mask: 0b1110000000000011 + size: 16 + branch: false + delay: 1 + DII: + index: 86 + encoding: 0b0000000000000000 + mask: 0b1111111111111111 + size: 16 + branch: false + delay: 1 + diff --git a/contrib/instr/TGC5C_slow.yaml b/contrib/instr/TGC5C_slow.yaml new file mode 100644 index 0000000..2aa7cac --- /dev/null +++ b/contrib/instr/TGC5C_slow.yaml @@ -0,0 +1,650 @@ +RV32I: + ADD: + branch: false + delay: 1 + encoding: 51 + index: 27 + mask: 4261441663 + size: 32 + ADDI: + branch: false + delay: 1 + encoding: 19 + index: 18 + mask: 28799 + size: 32 + AND: + branch: false + delay: 1 + encoding: 28723 + index: 36 + mask: 4261441663 + size: 32 + ANDI: + branch: false + delay: 1 + encoding: 28691 + index: 23 + mask: 28799 + size: 32 + AUIPC: + branch: false + delay: 1 + encoding: 23 + index: 1 + mask: 127 + size: 32 + BEQ: + branch: true + delay: + - 1 + - 2 + encoding: 99 + index: 4 + mask: 28799 + size: 32 + BGE: + branch: true + delay: + - 1 + - 2 + encoding: 20579 + index: 7 + mask: 28799 + size: 32 + BGEU: + branch: true + delay: + - 1 + - 2 + encoding: 28771 + index: 9 + mask: 28799 + size: 32 + BLT: + branch: true + delay: + - 1 + - 2 + encoding: 16483 + index: 6 + mask: 28799 + size: 32 + BLTU: + branch: true + delay: + - 1 + - 2 + encoding: 24675 + index: 8 + mask: 28799 + size: 32 + BNE: + branch: true + delay: + - 1 + - 2 + encoding: 4195 + index: 5 + mask: 28799 + size: 32 + EBREAK: + attributes: + - - name:no_cont + branch: false + delay: 3 + encoding: 1048691 + index: 39 + mask: 4294967295 + size: 32 + ECALL: + attributes: + - - name:no_cont + branch: false + delay: 1 + encoding: 115 + index: 38 + mask: 4294967295 + size: 32 + FENCE: + branch: false + delay: 1 + encoding: 15 + index: 37 + mask: 28799 + size: 32 + JAL: + branch: true + delay: 2 + encoding: 111 + index: 2 + mask: 127 + size: 32 + JALR: + branch: true + delay: 2 + encoding: 103 + index: 3 + mask: 28799 + size: 32 + LB: + branch: false + delay: 2 + encoding: 3 + index: 10 + mask: 28799 + size: 32 + LBU: + branch: false + delay: 2 + encoding: 16387 + index: 13 + mask: 28799 + size: 32 + LH: + branch: false + delay: 2 + encoding: 4099 + index: 11 + mask: 28799 + size: 32 + LHU: + branch: false + delay: 2 + encoding: 20483 + index: 14 + mask: 28799 + size: 32 + LUI: + branch: false + delay: 1 + encoding: 55 + index: 0 + mask: 127 + size: 32 + LW: + branch: false + delay: 2 + encoding: 8195 + index: 12 + mask: 28799 + size: 32 + MRET: + attributes: + - - name:no_cont + branch: false + delay: 2 + encoding: 807403635 + index: 40 + mask: 4294967295 + size: 32 + OR: + branch: false + delay: 1 + encoding: 24627 + index: 35 + mask: 4261441663 + size: 32 + ORI: + branch: false + delay: 1 + encoding: 24595 + index: 22 + mask: 28799 + size: 32 + SB: + branch: false + delay: 1 + encoding: 35 + index: 15 + mask: 28799 + size: 32 + SH: + branch: false + delay: 1 + encoding: 4131 + index: 16 + mask: 28799 + size: 32 + SLL: + branch: false + delay: X_24:20 + encoding: 4147 + index: 29 + mask: 4261441663 + size: 32 + SLLI: + branch: false + delay: u_24:20 + encoding: 4115 + index: 24 + mask: 4261441663 + size: 32 + SLT: + branch: false + delay: 1 + encoding: 8243 + index: 30 + mask: 4261441663 + size: 32 + SLTI: + branch: false + delay: 1 + encoding: 8211 + index: 19 + mask: 28799 + size: 32 + SLTIU: + branch: false + delay: 1 + encoding: 12307 + index: 20 + mask: 28799 + size: 32 + SLTU: + branch: false + delay: 1 + encoding: 12339 + index: 31 + mask: 4261441663 + size: 32 + SRA: + branch: false + delay: X_24:20 + encoding: 1073762355 + index: 34 + mask: 4261441663 + size: 32 + SRAI: + branch: false + delay: u_24:20 + encoding: 1073762323 + index: 26 + mask: 4261441663 + size: 32 + SRL: + branch: false + delay: X_24:20 + encoding: 20531 + index: 33 + mask: 4261441663 + size: 32 + SRLI: + branch: false + delay: u_24:20 + encoding: 20499 + index: 25 + mask: 4261441663 + size: 32 + SUB: + branch: false + delay: 1 + encoding: 1073741875 + index: 28 + mask: 4261441663 + size: 32 + SW: + branch: false + delay: 1 + encoding: 8227 + index: 17 + mask: 28799 + size: 32 + WFI: + branch: false + delay: 1 + encoding: 273678451 + index: 41 + mask: 4294967295 + size: 32 + XOR: + branch: false + delay: 1 + encoding: 16435 + index: 32 + mask: 4261441663 + size: 32 + XORI: + branch: false + delay: 1 + encoding: 16403 + index: 21 + mask: 28799 + size: 32 +RV32M: + DIV: + branch: false + delay: 33 + encoding: 33570867 + index: 53 + mask: 4261441663 + size: 32 + DIVU: + branch: false + delay: 33 + encoding: 33574963 + index: 54 + mask: 4261441663 + size: 32 + MUL: + branch: false + delay: 32 + encoding: 33554483 + index: 49 + mask: 4261441663 + size: 32 + MULH: + branch: false + delay: 32 + encoding: 33558579 + index: 50 + mask: 4261441663 + size: 32 + MULHSU: + branch: false + delay: 32 + encoding: 33562675 + index: 51 + mask: 4261441663 + size: 32 + MULHU: + branch: false + delay: 32 + encoding: 33566771 + index: 52 + mask: 4261441663 + size: 32 + REM: + branch: false + delay: 33 + encoding: 33579059 + index: 55 + mask: 4261441663 + size: 32 + REMU: + branch: false + delay: 33 + encoding: 33583155 + index: 56 + mask: 4261441663 + size: 32 +Zca: + C__ADD: + branch: false + delay: 1 + encoding: 36866 + index: 82 + mask: 61443 + size: 16 + C__ADDI: + branch: false + delay: 1 + encoding: 1 + index: 60 + mask: 57347 + size: 16 + C__ADDI16SP: + branch: false + delay: 1 + encoding: 24833 + index: 65 + mask: 61315 + size: 16 + C__ADDI4SPN: + branch: false + delay: 1 + encoding: 0 + index: 57 + mask: 57347 + size: 16 + C__AND: + branch: false + delay: 1 + encoding: 35937 + index: 73 + mask: 64611 + size: 16 + C__ANDI: + branch: false + delay: 1 + encoding: 34817 + index: 69 + mask: 60419 + size: 16 + C__BEQZ: + branch: true + delay: + - 1 + - 2 + encoding: 49153 + index: 75 + mask: 57347 + size: 16 + C__BNEZ: + branch: true + delay: + - 1 + - 2 + encoding: 57345 + index: 76 + mask: 57347 + size: 16 + C__EBREAK: + branch: false + delay: 3 + encoding: 36866 + index: 84 + mask: 65535 + size: 16 + C__J: + branch: true + delay: 1 + encoding: 40961 + index: 74 + mask: 57347 + size: 16 + C__JAL: + attributes: + - - name:enable + - value:1 + branch: true + delay: 1 + encoding: 8193 + index: 62 + mask: 57347 + size: 16 + C__JALR: + branch: true + delay: 1 + encoding: 36866 + index: 83 + mask: 61567 + size: 16 + C__JR: + branch: true + delay: 1 + encoding: 32770 + index: 80 + mask: 61567 + size: 16 + C__LI: + branch: false + delay: 1 + encoding: 16385 + index: 63 + mask: 57347 + size: 16 + C__LUI: + branch: false + delay: 1 + encoding: 24577 + index: 64 + mask: 57347 + size: 16 + C__LW: + branch: false + delay: 2 + encoding: 16384 + index: 58 + mask: 57347 + size: 16 + C__LWSP: + branch: false + delay: 2 + encoding: 16386 + index: 78 + mask: 57347 + size: 16 + C__MV: + branch: false + delay: 1 + encoding: 32770 + index: 79 + mask: 61443 + size: 16 + C__NOP: + branch: false + delay: 1 + encoding: 1 + index: 61 + mask: 61315 + size: 16 + C__OR: + branch: false + delay: 1 + encoding: 35905 + index: 72 + mask: 64611 + size: 16 + C__SLLI: + attributes: + - - name:enable + - value:1 + branch: false + delay: u_12:12*16+u_6:2 + encoding: 2 + index: 77 + mask: 61443 + size: 16 + C__SRAI: + attributes: + - - name:enable + - value:1 + branch: false + delay: u_12:12*16+u_6:2 + encoding: 33793 + index: 68 + mask: 64515 + size: 16 + C__SRLI: + attributes: + - - name:enable + - value:1 + branch: false + delay: u_12:12*16+u_6:2 + encoding: 32769 + index: 67 + mask: 64515 + size: 16 + C__SUB: + branch: false + delay: 1 + encoding: 35841 + index: 70 + mask: 64611 + size: 16 + C__SW: + branch: false + delay: 1 + encoding: 49152 + index: 59 + mask: 57347 + size: 16 + C__SWSP: + branch: false + delay: 1 + encoding: 49154 + index: 85 + mask: 57347 + size: 16 + C__XOR: + branch: false + delay: 1 + encoding: 35873 + index: 71 + mask: 64611 + size: 16 + DII: + branch: false + delay: 1 + encoding: 0 + index: 86 + mask: 65535 + size: 16 + __reserved_clui: + branch: false + delay: 1 + encoding: 24577 + index: 66 + mask: 61567 + size: 16 + __reserved_cmv: + branch: false + delay: 1 + encoding: 32770 + index: 81 + mask: 65535 + size: 16 +Zicsr: + CSRRC: + branch: false + delay: 1 + encoding: 12403 + index: 44 + mask: 28799 + size: 32 + CSRRCI: + branch: false + delay: 1 + encoding: 28787 + index: 47 + mask: 28799 + size: 32 + CSRRS: + branch: false + delay: 1 + encoding: 8307 + index: 43 + mask: 28799 + size: 32 + CSRRSI: + branch: false + delay: 1 + encoding: 24691 + index: 46 + mask: 28799 + size: 32 + CSRRW: + branch: false + delay: 1 + encoding: 4211 + index: 42 + mask: 28799 + size: 32 + CSRRWI: + branch: false + delay: 1 + encoding: 20595 + index: 45 + mask: 28799 + size: 32 +Zifencei: + FENCE_I: + attributes: + - - name:flush + branch: false + delay: 1 + encoding: 4111 + index: 48 + mask: 28799 + size: 32 diff --git a/contrib/pa/.gitignore b/contrib/pa/.gitignore new file mode 100644 index 0000000..d534727 --- /dev/null +++ b/contrib/pa/.gitignore @@ -0,0 +1,3 @@ +/results +/cwr +/*.xml diff --git a/contrib/pa/README.md b/contrib/pa/README.md new file mode 100644 index 0000000..3c1c287 --- /dev/null +++ b/contrib/pa/README.md @@ -0,0 +1,43 @@ +# Notes + +* requires conan version 1.59 +* requires decent cmake version 3.23 + +Setup for tcsh: + +``` +git clone --recursive -b develop https://git.minres.com/TGFS/TGC-ISS.git +cd TGC-ISS/ +setenv TGFS_INSTALL_ROOT `pwd`/install +setenv COWAREHOME +setenv SNPSLMD_LICENSE_FILE +source $COWAREHOME/SLS/linux/setup.csh pae +setenv SNPS_ENABLE_MEM_ON_DEMAND_IN_GENERIC_MEM 1 +setenv PATH $COWAREHOME/common/bin/:${PATH} +setenv CC $COWAREHOME/SLS/linux/common/bin/gcc +setenv CXX $COWAREHOME/SLS/linux/common/bin/g++ +cmake -S . -B build/PA -DCMAKE_BUILD_TYPE=Debug -DUSE_CWR_SYSTEMC=ON -DBUILD_SHARED_LIBS=ON \ + -DCODEGEN=OFF -DCMAKE_INSTALL_PREFIX=${TGFS_INSTALL_ROOT} +cmake --build build/PA --target install -j16 +cd dbt-rise-tgc/contrib/pa +# import the TGC core itself +pct tgc_import_tb.tcl +``` + +Setup for bash: + +``` +git clone --recursive -b develop https://git.minres.com/TGFS/TGC-ISS.git +cd TGC-ISS/ +export TGFS_INSTALL_ROOT `pwd`/install +module load tools/pa/T-2022.06 +export SNPS_ENABLE_MEM_ON_DEMAND_IN_GENERIC_MEM=1 +export CC=$COWAREHOME/SLS/linux/common/bin/gcc +export CXX=$COWAREHOME/SLS/linux/common/bin/g++ +cmake -S . -B build/PA -DCMAKE_BUILD_TYPE=Debug -DUSE_CWR_SYSTEMC=ON -DBUILD_SHARED_LIBS=ON \ + -DCODEGEN=OFF -DCMAKE_INSTALL_PREFIX=${TGFS_INSTALL_ROOT} +cmake --build build/PA --target install -j16 +cd dbt-rise-tgc/contrib/pa +# import the TGC core itself +pct tgc_import_tb.tcl +``` \ No newline at end of file diff --git a/contrib/build.tcl b/contrib/pa/build.tcl similarity index 95% rename from contrib/build.tcl rename to contrib/pa/build.tcl index 023815b..e4da561 100644 --- a/contrib/build.tcl +++ b/contrib/pa/build.tcl @@ -16,7 +16,7 @@ namespace eval Specification { set libdir "${install_dir}/lib64" set preprocessorOptions [concat $preprocessorOptions "-I${incldir}"] # Set the Linker paths. - set linkerOptions [concat $linkerOptions "-Wl,-rpath,${libdir} -L${libdir} -ldbt-rise-tgc_sc"] + set linkerOptions [concat $linkerOptions "-Wl,-rpath,${libdir} -L${libdir} -ldbt-rise-tgc_sc -lscc-sysc"] } default { puts stderr "ERROR: \"$target\" is not supported, [::scsh::version]" diff --git a/contrib/pa/hello.dis b/contrib/pa/hello.dis new file mode 100644 index 0000000..ff86ca8 --- /dev/null +++ b/contrib/pa/hello.dis @@ -0,0 +1,2092 @@ + +hello: file format elf32-littleriscv + + +Disassembly of section .init: + +00000020 <_start>: + .section .init + .globl _start + .type _start,@function + +_start: + la gp, _gp + 20: 10000197 auipc gp,0x10000 + 24: 7e018193 addi gp,gp,2016 # 10000800 <_gp> + la sp, _sp + 28: 10004117 auipc sp,0x10004 + 2c: fd810113 addi sp,sp,-40 # 10004000 <_sp> + + /* Load data section */ + la a0, _data_lma + 30: 00001517 auipc a0,0x1 + 34: 72850513 addi a0,a0,1832 # 1758 <_data_lma> + la a1, _data + 38: 10000597 auipc a1,0x10000 + 3c: fc858593 addi a1,a1,-56 # 10000000 <_data> + la a2, _edata + 40: 10000617 auipc a2,0x10000 + 44: fc860613 addi a2,a2,-56 # 10000008 <__bss_start> + bgeu a1, a2, 2f + 48: 00c5fc63 bgeu a1,a2,60 <_start+0x40> +1: + lw t0, (a0) + 4c: 00052283 lw t0,0(a0) + sw t0, (a1) + 50: 0055a023 sw t0,0(a1) + addi a0, a0, 4 + 54: 00450513 addi a0,a0,4 + addi a1, a1, 4 + 58: 00458593 addi a1,a1,4 + bltu a1, a2, 1b + 5c: fec5e8e3 bltu a1,a2,4c <_start+0x2c> +2: + + /* Clear bss section */ + la a0, __bss_start + 60: 10000517 auipc a0,0x10000 + 64: fa850513 addi a0,a0,-88 # 10000008 <__bss_start> + la a1, _end + 68: 10000597 auipc a1,0x10000 + 6c: fa058593 addi a1,a1,-96 # 10000008 <__bss_start> + bgeu a0, a1, 2f + 70: 00b57863 bgeu a0,a1,80 <_start+0x60> +1: + sw zero, (a0) + 74: 00052023 sw zero,0(a0) + addi a0, a0, 4 + 78: 00450513 addi a0,a0,4 + bltu a0, a1, 1b + 7c: feb56ce3 bltu a0,a1,74 <_start+0x54> + fssr x0 +1: +#endif + + /* argc = argv = 0 */ + li a0, 0 + 80: 00000513 li a0,0 + li a1, 0 + 84: 00000593 li a1,0 + call main + 88: 008000ef jal ra,90
+ tail _exit + 8c: 3300006f j 3bc <__wrap__exit> + +Disassembly of section .text: + +00000090
: + return result; + +} + +int main() +{ + 90: fe010113 addi sp,sp,-32 + volatile int result = 1; + 94: 00100793 li a5,1 +{ + 98: 00812c23 sw s0,24(sp) + 9c: 00912a23 sw s1,20(sp) + a0: 00112e23 sw ra,28(sp) + volatile int result = 1; + a4: 00f12623 sw a5,12(sp) + for (int ii = 1; ii <= i; ii++) { + a8: 00100413 li s0,1 + ac: 00b00493 li s1,11 + result = result * ii; + b0: 00c12503 lw a0,12(sp) + b4: 00040593 mv a1,s0 + for (int ii = 1; ii <= i; ii++) { + b8: 00140413 addi s0,s0,1 + result = result * ii; + bc: 2b0010ef jal ra,136c <__mulsi3> + c0: 00a12623 sw a0,12(sp) + for (int ii = 1; ii <= i; ii++) { + c4: fe9416e3 bne s0,s1,b0 + return result; + c8: 00c12783 lw a5,12(sp) +// *(uint32_t*)(GPIO_CTRL_ADDR+GPIO_IOF_SEL) &= ~IOF0_UART0_MASK; +// *(uint32_t*)(GPIO_CTRL_ADDR+GPIO_IOF_EN) |= IOF0_UART0_MASK; + volatile int result = factorial (10); + printf("Factorial is %d\n", result); + cc: 00001517 auipc a0,0x1 + d0: 3c450513 addi a0,a0,964 # 1490 <__clzsi2+0x4c> + volatile int result = factorial (10); + d4: 00f12423 sw a5,8(sp) + printf("Factorial is %d\n", result); + d8: 00812583 lw a1,8(sp) + dc: 285000ef jal ra,b60 <__wrap_printf> + printf("End of execution"); + e0: 00001517 auipc a0,0x1 + e4: 3c450513 addi a0,a0,964 # 14a4 <__clzsi2+0x60> + e8: 279000ef jal ra,b60 <__wrap_printf> + return 0; +} + ec: 01c12083 lw ra,28(sp) + f0: 01812403 lw s0,24(sp) + f4: 01412483 lw s1,20(sp) + f8: 00000513 li a0,0 + fc: 02010113 addi sp,sp,32 + 100: 00008067 ret + +00000104 : + + .section .text.entry + .align 2 + .global trap_entry +trap_entry: + addi sp, sp, -32*REGBYTES + 104: f8010113 addi sp,sp,-128 + + STORE x1, 1*REGBYTES(sp) + 108: 00112223 sw ra,4(sp) + STORE x2, 2*REGBYTES(sp) + 10c: 00212423 sw sp,8(sp) + STORE x3, 3*REGBYTES(sp) + 110: 00312623 sw gp,12(sp) + STORE x4, 4*REGBYTES(sp) + 114: 00412823 sw tp,16(sp) + STORE x5, 5*REGBYTES(sp) + 118: 00512a23 sw t0,20(sp) + STORE x6, 6*REGBYTES(sp) + 11c: 00612c23 sw t1,24(sp) + STORE x7, 7*REGBYTES(sp) + 120: 00712e23 sw t2,28(sp) + STORE x8, 8*REGBYTES(sp) + 124: 02812023 sw s0,32(sp) + STORE x9, 9*REGBYTES(sp) + 128: 02912223 sw s1,36(sp) + STORE x10, 10*REGBYTES(sp) + 12c: 02a12423 sw a0,40(sp) + STORE x11, 11*REGBYTES(sp) + 130: 02b12623 sw a1,44(sp) + STORE x12, 12*REGBYTES(sp) + 134: 02c12823 sw a2,48(sp) + STORE x13, 13*REGBYTES(sp) + 138: 02d12a23 sw a3,52(sp) + STORE x14, 14*REGBYTES(sp) + 13c: 02e12c23 sw a4,56(sp) + STORE x15, 15*REGBYTES(sp) + 140: 02f12e23 sw a5,60(sp) +#ifndef __riscv_abi_rve + STORE x16, 16*REGBYTES(sp) + 144: 05012023 sw a6,64(sp) + STORE x17, 17*REGBYTES(sp) + 148: 05112223 sw a7,68(sp) + STORE x18, 18*REGBYTES(sp) + 14c: 05212423 sw s2,72(sp) + STORE x19, 19*REGBYTES(sp) + 150: 05312623 sw s3,76(sp) + STORE x20, 20*REGBYTES(sp) + 154: 05412823 sw s4,80(sp) + STORE x21, 21*REGBYTES(sp) + 158: 05512a23 sw s5,84(sp) + STORE x22, 22*REGBYTES(sp) + 15c: 05612c23 sw s6,88(sp) + STORE x23, 23*REGBYTES(sp) + 160: 05712e23 sw s7,92(sp) + STORE x24, 24*REGBYTES(sp) + 164: 07812023 sw s8,96(sp) + STORE x25, 25*REGBYTES(sp) + 168: 07912223 sw s9,100(sp) + STORE x26, 26*REGBYTES(sp) + 16c: 07a12423 sw s10,104(sp) + STORE x27, 27*REGBYTES(sp) + 170: 07b12623 sw s11,108(sp) + STORE x28, 28*REGBYTES(sp) + 174: 07c12823 sw t3,112(sp) + STORE x29, 29*REGBYTES(sp) + 178: 07d12a23 sw t4,116(sp) + STORE x30, 30*REGBYTES(sp) + 17c: 07e12c23 sw t5,120(sp) + STORE x31, 31*REGBYTES(sp) + 180: 07f12e23 sw t6,124(sp) +#endif + csrr a0, mcause + 184: 34202573 csrr a0,mcause + csrr a1, mepc + 188: 341025f3 csrr a1,mepc + mv a2, sp + 18c: 00010613 mv a2,sp + call handle_trap + 190: 11c000ef jal ra,2ac + csrw mepc, a0 + 194: 34151073 csrw mepc,a0 + + # Remain in M-mode after mret + li t0, MSTATUS_MPP + 198: 000022b7 lui t0,0x2 + 19c: 80028293 addi t0,t0,-2048 # 1800 <_data_lma+0xa8> + csrs mstatus, t0 + 1a0: 3002a073 csrs mstatus,t0 + + LOAD x1, 1*REGBYTES(sp) + 1a4: 00412083 lw ra,4(sp) + LOAD x2, 2*REGBYTES(sp) + 1a8: 00812103 lw sp,8(sp) + LOAD x3, 3*REGBYTES(sp) + 1ac: 00c12183 lw gp,12(sp) + LOAD x4, 4*REGBYTES(sp) + 1b0: 01012203 lw tp,16(sp) + LOAD x5, 5*REGBYTES(sp) + 1b4: 01412283 lw t0,20(sp) + LOAD x6, 6*REGBYTES(sp) + 1b8: 01812303 lw t1,24(sp) + LOAD x7, 7*REGBYTES(sp) + 1bc: 01c12383 lw t2,28(sp) + LOAD x8, 8*REGBYTES(sp) + 1c0: 02012403 lw s0,32(sp) + LOAD x9, 9*REGBYTES(sp) + 1c4: 02412483 lw s1,36(sp) + LOAD x10, 10*REGBYTES(sp) + 1c8: 02812503 lw a0,40(sp) + LOAD x11, 11*REGBYTES(sp) + 1cc: 02c12583 lw a1,44(sp) + LOAD x12, 12*REGBYTES(sp) + 1d0: 03012603 lw a2,48(sp) + LOAD x13, 13*REGBYTES(sp) + 1d4: 03412683 lw a3,52(sp) + LOAD x14, 14*REGBYTES(sp) + 1d8: 03812703 lw a4,56(sp) + LOAD x15, 15*REGBYTES(sp) + 1dc: 03c12783 lw a5,60(sp) +#ifndef __riscv_abi_rve + LOAD x16, 16*REGBYTES(sp) + 1e0: 04012803 lw a6,64(sp) + LOAD x17, 17*REGBYTES(sp) + 1e4: 04412883 lw a7,68(sp) + LOAD x18, 18*REGBYTES(sp) + 1e8: 04812903 lw s2,72(sp) + LOAD x19, 19*REGBYTES(sp) + 1ec: 04c12983 lw s3,76(sp) + LOAD x20, 20*REGBYTES(sp) + 1f0: 05012a03 lw s4,80(sp) + LOAD x21, 21*REGBYTES(sp) + 1f4: 05412a83 lw s5,84(sp) + LOAD x22, 22*REGBYTES(sp) + 1f8: 05812b03 lw s6,88(sp) + LOAD x23, 23*REGBYTES(sp) + 1fc: 05c12b83 lw s7,92(sp) + LOAD x24, 24*REGBYTES(sp) + 200: 06012c03 lw s8,96(sp) + LOAD x25, 25*REGBYTES(sp) + 204: 06412c83 lw s9,100(sp) + LOAD x26, 26*REGBYTES(sp) + 208: 06812d03 lw s10,104(sp) + LOAD x27, 27*REGBYTES(sp) + 20c: 06c12d83 lw s11,108(sp) + LOAD x28, 28*REGBYTES(sp) + 210: 07012e03 lw t3,112(sp) + LOAD x29, 29*REGBYTES(sp) + 214: 07412e83 lw t4,116(sp) + LOAD x30, 30*REGBYTES(sp) + 218: 07812f03 lw t5,120(sp) + LOAD x31, 31*REGBYTES(sp) + 21c: 07c12f83 lw t6,124(sp) +#endif + addi sp, sp, 32*REGBYTES + 220: 08010113 addi sp,sp,128 + mret + 224: 30200073 mret + +.weak handle_trap +handle_trap: +1: + j 1b + 228: 0000006f j 228 + +0000022c : +int factorial(int i){ + 22c: fe010113 addi sp,sp,-32 + volatile int result = 1; + 230: 00100793 li a5,1 +int factorial(int i){ + 234: 00112e23 sw ra,28(sp) + 238: 00812c23 sw s0,24(sp) + 23c: 00912a23 sw s1,20(sp) + volatile int result = 1; + 240: 00f12623 sw a5,12(sp) + for (int ii = 1; ii <= i; ii++) { + 244: 02a05263 blez a0,268 + 248: 00150493 addi s1,a0,1 + 24c: 00100413 li s0,1 + result = result * ii; + 250: 00c12503 lw a0,12(sp) + 254: 00040593 mv a1,s0 + for (int ii = 1; ii <= i; ii++) { + 258: 00140413 addi s0,s0,1 + result = result * ii; + 25c: 110010ef jal ra,136c <__mulsi3> + 260: 00a12623 sw a0,12(sp) + for (int ii = 1; ii <= i; ii++) { + 264: fe9416e3 bne s0,s1,250 +} + 268: 01c12083 lw ra,28(sp) + 26c: 01812403 lw s0,24(sp) + return result; + 270: 00c12503 lw a0,12(sp) +} + 274: 01412483 lw s1,20(sp) + 278: 02010113 addi sp,sp,32 + 27c: 00008067 ret + +00000280 : +#if __riscv_xlen==32 + +static uint32_t mtime_hi(void) +{ + unsigned long ret; + __asm volatile("rdtimeh %0":"=r"(ret)); + 280: c81027f3 rdtimeh a5 + __asm volatile("rdtime %0":"=r"(ret)); + 284: c0102573 rdtime a0 + __asm volatile("rdtimeh %0":"=r"(ret)); + 288: c81025f3 rdtimeh a1 +uint64_t get_timer_value() +{ + while (1) { + uint32_t hi = mtime_hi(); + uint32_t lo = mtime_lo(); + if (hi == mtime_hi()) + 28c: fef59ae3 bne a1,a5,280 + return ((uint64_t)hi << 32) | lo; + } +} + 290: 00008067 ret + +00000294 : +#endif + +unsigned long get_timer_freq() +{ + return 32768; +} + 294: 00008537 lui a0,0x8 + 298: 00008067 ret + +0000029c : + +unsigned long get_cpu_freq() +{ + return 10000000; + 29c: 00989537 lui a0,0x989 +} + 2a0: 68050513 addi a0,a0,1664 # 989680 <_data_lma+0x987f28> + 2a4: 00008067 ret + +000002a8 : + +void init_pll(void){ + +} + 2a8: 00008067 ret + +000002ac : +#ifdef USE_M_TIME +extern void handle_m_time_interrupt(); +#endif + +uintptr_t handle_trap(uintptr_t mcause, uintptr_t epc) +{ + 2ac: ff010113 addi sp,sp,-16 + 2b0: 00812423 sw s0,8(sp) + } else if ((mcause & MCAUSE_INT) && ((mcause & MCAUSE_CAUSE) == IRQ_M_TIMER)){ + handle_m_time_interrupt(); +#endif + } + else { + write(1, "trap\n", 5); + 2b4: 00500613 li a2,5 +{ + 2b8: 00050413 mv s0,a0 + write(1, "trap\n", 5); + 2bc: 00001597 auipc a1,0x1 + 2c0: 1fc58593 addi a1,a1,508 # 14b8 <__clzsi2+0x74> + 2c4: 00100513 li a0,1 +{ + 2c8: 00112623 sw ra,12(sp) + write(1, "trap\n", 5); + 2cc: 05c000ef jal ra,328 <__wrap_write> + _exit(1 + mcause); + 2d0: 00140513 addi a0,s0,1 + 2d4: 0e8000ef jal ra,3bc <__wrap__exit> + +000002d8 <_init>: +void _init() +{ + +#ifndef NO_INIT + init_pll(); + printf("core freq at %d Hz\n", get_cpu_freq()); + 2d8: 009895b7 lui a1,0x989 +{ + 2dc: ff010113 addi sp,sp,-16 + printf("core freq at %d Hz\n", get_cpu_freq()); + 2e0: 68058593 addi a1,a1,1664 # 989680 <_data_lma+0x987f28> + 2e4: 00001517 auipc a0,0x1 + 2e8: 1dc50513 addi a0,a0,476 # 14c0 <__clzsi2+0x7c> +{ + 2ec: 00112623 sw ra,12(sp) + printf("core freq at %d Hz\n", get_cpu_freq()); + 2f0: 071000ef jal ra,b60 <__wrap_printf> + write_csr(mtvec, &trap_entry); + 2f4: 00000797 auipc a5,0x0 + 2f8: e1078793 addi a5,a5,-496 # 104 + 2fc: 30579073 csrw mtvec,a5 + if (read_csr(misa) & (1 << ('F' - 'A'))) { // if F extension is present + 300: 301027f3 csrr a5,misa + 304: 0207f793 andi a5,a5,32 + 308: 00078863 beqz a5,318 <_init+0x40> + write_csr(mstatus, MSTATUS_FS); // allow FPU instructions without trapping + 30c: 000067b7 lui a5,0x6 + 310: 30079073 csrw mstatus,a5 + write_csr(fcsr, 0); // initialize rounding mode, undefined at reset + 314: 00305073 csrwi fcsr,0 + } +#endif + +} + 318: 00c12083 lw ra,12(sp) + 31c: 01010113 addi sp,sp,16 + 320: 00008067 ret + +00000324 <_fini>: + +void _fini() +{ +} + 324: 00008067 ret + +00000328 <__wrap_write>: + +#include "platform.h" +#include "stub.h" + +ssize_t __wrap_write(int fd, const void* ptr, size_t len) +{ + 328: ff010113 addi sp,sp,-16 + 32c: 00812423 sw s0,8(sp) + 330: 00912223 sw s1,4(sp) + 334: 00112623 sw ra,12(sp) + 338: 00058413 mv s0,a1 + 33c: 00060493 mv s1,a2 + const uint8_t * current = (const char *)ptr; + + if (isatty(fd)) { + 340: 070000ef jal ra,3b0 <__wrap_isatty> + 344: 06050263 beqz a0,3a8 <__wrap_write+0x80> + for (size_t jj = 0; jj < len; jj++) { + 348: 02048c63 beqz s1,380 <__wrap_write+0x58> + 34c: 00040593 mv a1,s0 + 350: 00940833 add a6,s0,s1 + while (UART0_REG(UART_REG_TXFIFO) & 0x80000000) ; + 354: ffff0737 lui a4,0xffff0 + UART0_REG(UART_REG_TXFIFO) = current[jj]; + + if (current[jj] == '\n') { + 358: 00a00693 li a3,10 + while (UART0_REG(UART_REG_TXFIFO) & 0x80000000) ; + UART0_REG(UART_REG_TXFIFO) = '\r'; + 35c: 00d00613 li a2,13 + while (UART0_REG(UART_REG_TXFIFO) & 0x80000000) ; + 360: 00072783 lw a5,0(a4) # ffff0000 + 364: fe07cee3 bltz a5,360 <__wrap_write+0x38> + UART0_REG(UART_REG_TXFIFO) = current[jj]; + 368: 0005c783 lbu a5,0(a1) + 36c: 00f72023 sw a5,0(a4) + if (current[jj] == '\n') { + 370: 0005c783 lbu a5,0(a1) + 374: 02d78263 beq a5,a3,398 <__wrap_write+0x70> + for (size_t jj = 0; jj < len; jj++) { + 378: 00158593 addi a1,a1,1 + 37c: ff0592e3 bne a1,a6,360 <__wrap_write+0x38> + } + } + return len; + 380: 00048513 mv a0,s1 + } + + return _stub(EBADF); +} + 384: 00c12083 lw ra,12(sp) + 388: 00812403 lw s0,8(sp) + 38c: 00412483 lw s1,4(sp) + 390: 01010113 addi sp,sp,16 + 394: 00008067 ret + while (UART0_REG(UART_REG_TXFIFO) & 0x80000000) ; + 398: 00072783 lw a5,0(a4) + 39c: fe07cee3 bltz a5,398 <__wrap_write+0x70> + UART0_REG(UART_REG_TXFIFO) = '\r'; + 3a0: 00c72023 sw a2,0(a4) + 3a4: fd5ff06f j 378 <__wrap_write+0x50> + return _stub(EBADF); + 3a8: fff00513 li a0,-1 + 3ac: fd9ff06f j 384 <__wrap_write+0x5c> + +000003b0 <__wrap_isatty>: + +#include + +int __wrap_isatty(int fd) +{ + if (fd == STDOUT_FILENO || fd == STDERR_FILENO) + 3b0: fff50513 addi a0,a0,-1 + return 1; + + return 0; +} + 3b4: 00253513 sltiu a0,a0,2 + 3b8: 00008067 ret + +000003bc <__wrap__exit>: +extern volatile uint32_t fromhost; + +void __wrap__exit(int code) +{ +//volatile uint32_t* leds = (uint32_t*) (GPIO_BASE_ADDR + GPIO_OUT_OFFSET); + const char message[] = "\nProgam has exited with code:"; + 3bc: 00001797 auipc a5,0x1 + 3c0: 11878793 addi a5,a5,280 # 14d4 <__clzsi2+0x90> + 3c4: 0007ae83 lw t4,0(a5) + 3c8: 0047ae03 lw t3,4(a5) + 3cc: 0087a303 lw t1,8(a5) + 3d0: 00c7a883 lw a7,12(a5) + 3d4: 0107a803 lw a6,16(a5) + 3d8: 0147a683 lw a3,20(a5) + 3dc: 0187a703 lw a4,24(a5) + 3e0: 01c7d783 lhu a5,28(a5) +{ + 3e4: fd010113 addi sp,sp,-48 +//*leds = (~(code)); + + write(STDERR_FILENO, message, sizeof(message) - 1); + 3e8: 01d00613 li a2,29 +{ + 3ec: 02812423 sw s0,40(sp) + write(STDERR_FILENO, message, sizeof(message) - 1); + 3f0: 00010593 mv a1,sp +{ + 3f4: 00050413 mv s0,a0 + write(STDERR_FILENO, message, sizeof(message) - 1); + 3f8: 00200513 li a0,2 + const char message[] = "\nProgam has exited with code:"; + 3fc: 00f11e23 sh a5,28(sp) +{ + 400: 02112623 sw ra,44(sp) + const char message[] = "\nProgam has exited with code:"; + 404: 01d12023 sw t4,0(sp) + 408: 01c12223 sw t3,4(sp) + 40c: 00612423 sw t1,8(sp) + 410: 01112623 sw a7,12(sp) + 414: 01012823 sw a6,16(sp) + 418: 00d12a23 sw a3,20(sp) + 41c: 00e12c23 sw a4,24(sp) + write(STDERR_FILENO, message, sizeof(message) - 1); + 420: f09ff0ef jal ra,328 <__wrap_write> + write_hex(STDERR_FILENO, code); + 424: 00040593 mv a1,s0 + 428: 00200513 li a0,2 + 42c: 028000ef jal ra,454 + write(STDERR_FILENO, "\n", 1); + 430: 00100613 li a2,1 + 434: 00001597 auipc a1,0x1 + 438: 08858593 addi a1,a1,136 # 14bc <__clzsi2+0x78> + 43c: 00200513 li a0,2 + tohost = code+1; + 440: 00140413 addi s0,s0,1 + write(STDERR_FILENO, "\n", 1); + 444: ee5ff0ef jal ra,328 <__wrap_write> + tohost = code+1; + 448: 00000797 auipc a5,0x0 + 44c: ba87a423 sw s0,-1112(a5) # fffffff0 + for (;;); + 450: 0000006f j 450 <__wrap__exit+0x94> + +00000454 : +#include +#include +#include "platform.h" + +void write_hex(int fd, uint32_t hex) +{ + 454: fd010113 addi sp,sp,-48 + 458: 02912223 sw s1,36(sp) + uint8_t ii; + uint8_t jj; + char towrite; + write(fd , "0x", 2); + 45c: 00200613 li a2,2 +{ + 460: 00058493 mv s1,a1 + write(fd , "0x", 2); + 464: 00001597 auipc a1,0x1 + 468: 09058593 addi a1,a1,144 # 14f4 <__clzsi2+0xb0> +{ + 46c: 02812423 sw s0,40(sp) + 470: 03212023 sw s2,32(sp) + 474: 01312e23 sw s3,28(sp) + 478: 01412c23 sw s4,24(sp) + 47c: 01512a23 sw s5,20(sp) + 480: 02112623 sw ra,44(sp) + 484: 00050913 mv s2,a0 + write(fd , "0x", 2); + 488: 01c00413 li s0,28 + 48c: e9dff0ef jal ra,328 <__wrap_write> + for (ii = 8 ; ii > 0; ii--) { + jj = ii - 1; + uint8_t digit = ((hex & (0xF << (jj*4))) >> (jj*4)); + 490: 00f00a93 li s5,15 + towrite = digit < 0xA ? ('0' + digit) : ('A' + (digit - 0xA)); + 494: 00900a13 li s4,9 + for (ii = 8 ; ii > 0; ii--) { + 498: ffc00993 li s3,-4 + 49c: 0240006f j 4c0 + towrite = digit < 0xA ? ('0' + digit) : ('A' + (digit - 0xA)); + 4a0: 0ff6f793 zext.b a5,a3 + for (ii = 8 ; ii > 0; ii--) { + 4a4: ffc40413 addi s0,s0,-4 + write(fd, &towrite, 1); + 4a8: 00100613 li a2,1 + 4ac: 00f10593 addi a1,sp,15 + 4b0: 00090513 mv a0,s2 + towrite = digit < 0xA ? ('0' + digit) : ('A' + (digit - 0xA)); + 4b4: 00f107a3 sb a5,15(sp) + write(fd, &towrite, 1); + 4b8: e71ff0ef jal ra,328 <__wrap_write> + for (ii = 8 ; ii > 0; ii--) { + 4bc: 05340063 beq s0,s3,4fc + uint8_t digit = ((hex & (0xF << (jj*4))) >> (jj*4)); + 4c0: 008a97b3 sll a5,s5,s0 + 4c4: 0097f7b3 and a5,a5,s1 + 4c8: 0087d7b3 srl a5,a5,s0 + 4cc: 0ff7f793 zext.b a5,a5 + towrite = digit < 0xA ? ('0' + digit) : ('A' + (digit - 0xA)); + 4d0: 03078693 addi a3,a5,48 + 4d4: 03778713 addi a4,a5,55 + 4d8: fcfa74e3 bgeu s4,a5,4a0 + 4dc: 0ff77793 zext.b a5,a4 + for (ii = 8 ; ii > 0; ii--) { + 4e0: ffc40413 addi s0,s0,-4 + write(fd, &towrite, 1); + 4e4: 00100613 li a2,1 + 4e8: 00f10593 addi a1,sp,15 + 4ec: 00090513 mv a0,s2 + towrite = digit < 0xA ? ('0' + digit) : ('A' + (digit - 0xA)); + 4f0: 00f107a3 sb a5,15(sp) + write(fd, &towrite, 1); + 4f4: e35ff0ef jal ra,328 <__wrap_write> + for (ii = 8 ; ii > 0; ii--) { + 4f8: fd3414e3 bne s0,s3,4c0 + } +} + 4fc: 02c12083 lw ra,44(sp) + 500: 02812403 lw s0,40(sp) + 504: 02412483 lw s1,36(sp) + 508: 02012903 lw s2,32(sp) + 50c: 01c12983 lw s3,28(sp) + 510: 01812a03 lw s4,24(sp) + 514: 01412a83 lw s5,20(sp) + 518: 03010113 addi sp,sp,48 + 51c: 00008067 ret + +00000520 : +} + +static void sprintf_putch(int ch, void** data) +{ + char** pstr = (char**)data; + **pstr = ch; + 520: 0005a783 lw a5,0(a1) + 524: 00a78023 sb a0,0(a5) + (*pstr)++; + 528: 0005a783 lw a5,0(a1) + 52c: 00178793 addi a5,a5,1 + 530: 00f5a023 sw a5,0(a1) +} + 534: 00008067 ret + +00000538 : +{ + 538: fe010113 addi sp,sp,-32 + 53c: 00a12623 sw a0,12(sp) + return write(STDOUT_FILENO, &ch, 1) == 1 ? ch : -1; + 540: 00100613 li a2,1 + 544: 00c10593 addi a1,sp,12 + 548: 00100513 li a0,1 +{ + 54c: 00112e23 sw ra,28(sp) + return write(STDOUT_FILENO, &ch, 1) == 1 ? ch : -1; + 550: dd9ff0ef jal ra,328 <__wrap_write> + 554: 00100793 li a5,1 + 558: 00f51a63 bne a0,a5,56c + 55c: 00c12503 lw a0,12(sp) +} + 560: 01c12083 lw ra,28(sp) + 564: 02010113 addi sp,sp,32 + 568: 00008067 ret + return write(STDOUT_FILENO, &ch, 1) == 1 ? ch : -1; + 56c: fff00513 li a0,-1 + 570: ff1ff06f j 560 + +00000574 : + for (char* p = buf; p < pbuf; p++) + putch(*p, putdat); +} + +static void vprintfmt(void (*putch)(int, void**), void **putdat, const char *fmt, va_list ap) +{ + 574: f1010113 addi sp,sp,-240 + 578: 0d512a23 sw s5,212(sp) + 57c: 40000ab7 lui s5,0x40000 + 580: fffa8793 addi a5,s5,-1 # 3fffffff <_sp+0x2fffbfff> + 584: 0d912223 sw s9,196(sp) + u.u &= ~(1ULL << 63); + 588: 80000cb7 lui s9,0x80000 + 58c: 00f12223 sw a5,4(sp) + 590: fffcc793 not a5,s9 +{ + 594: 0e812423 sw s0,232(sp) + 598: 0e912223 sw s1,228(sp) + 59c: 0f212023 sw s2,224(sp) + 5a0: 0d312e23 sw s3,220(sp) + 5a4: 0e112623 sw ra,236(sp) + 5a8: 0d412c23 sw s4,216(sp) + 5ac: 0d612823 sw s6,208(sp) + 5b0: 0d712623 sw s7,204(sp) + 5b4: 0d812423 sw s8,200(sp) + 5b8: 0da12023 sw s10,192(sp) + 5bc: 0bb12e23 sw s11,188(sp) + 5c0: 00050913 mv s2,a0 + 5c4: 00058493 mv s1,a1 + 5c8: 00060413 mv s0,a2 + 5cc: 00d12023 sw a3,0(sp) + unsigned long num; + int base, lflag, width, precision, altflag; + char padc; + + while (1) { + while ((ch = *(unsigned char *) fmt) != '%') { + 5d0: 02500993 li s3,37 + u.u &= ~(1ULL << 63); + 5d4: 00f12423 sw a5,8(sp) + while ((ch = *(unsigned char *) fmt) != '%') { + 5d8: 0140006f j 5ec + if (ch == '\0') + 5dc: 06050263 beqz a0,640 + return; + fmt++; + putch(ch, putdat); + 5e0: 00048593 mv a1,s1 + fmt++; + 5e4: 00140413 addi s0,s0,1 + putch(ch, putdat); + 5e8: 000900e7 jalr s2 + while ((ch = *(unsigned char *) fmt) != '%') { + 5ec: 00044503 lbu a0,0(s0) + 5f0: ff3516e3 bne a0,s3,5dc + width = -1; + precision = -1; + lflag = 0; + altflag = 0; + reswitch: + switch (ch = *(unsigned char *) fmt++) { + 5f4: 00144683 lbu a3,1(s0) + fmt++; + 5f8: 00140d93 addi s11,s0,1 + 5fc: 000d8713 mv a4,s11 + padc = ' '; + 600: 02000b93 li s7,32 + precision = -1; + 604: fff00d13 li s10,-1 + width = -1; + 608: fff00b13 li s6,-1 + switch (ch = *(unsigned char *) fmt++) { + 60c: 05500593 li a1,85 + case '8': + case '9': + for (precision = 0; ; ++fmt) { + precision = precision * 10 + ch - '0'; + ch = *fmt; + if (ch < '0' || ch > '9') + 610: 00900513 li a0,9 + switch (ch = *(unsigned char *) fmt++) { + 614: fdd68793 addi a5,a3,-35 + 618: 0ff7f793 zext.b a5,a5 + 61c: 00170413 addi s0,a4,1 + 620: 06f5ec63 bltu a1,a5,698 + 624: 00001617 auipc a2,0x1 + 628: edc60613 addi a2,a2,-292 # 1500 <__clzsi2+0xbc> + 62c: 00279793 slli a5,a5,0x2 + 630: 00c787b3 add a5,a5,a2 + 634: 0007a783 lw a5,0(a5) + 638: 00c787b3 add a5,a5,a2 + 63c: 00078067 jr a5 + putch('%', putdat); + fmt = last_fmt; + break; + } + } +} + 640: 0ec12083 lw ra,236(sp) + 644: 0e812403 lw s0,232(sp) + 648: 0e412483 lw s1,228(sp) + 64c: 0e012903 lw s2,224(sp) + 650: 0dc12983 lw s3,220(sp) + 654: 0d812a03 lw s4,216(sp) + 658: 0d412a83 lw s5,212(sp) + 65c: 0d012b03 lw s6,208(sp) + 660: 0cc12b83 lw s7,204(sp) + 664: 0c812c03 lw s8,200(sp) + 668: 0c412c83 lw s9,196(sp) + 66c: 0c012d03 lw s10,192(sp) + 670: 0bc12d83 lw s11,188(sp) + 674: 0f010113 addi sp,sp,240 + 678: 00008067 ret + padc = '0'; + 67c: 00068b93 mv s7,a3 + goto reswitch; + 680: 00174683 lbu a3,1(a4) + switch (ch = *(unsigned char *) fmt++) { + 684: 00040713 mv a4,s0 + 688: 00170413 addi s0,a4,1 + 68c: fdd68793 addi a5,a3,-35 + 690: 0ff7f793 zext.b a5,a5 + 694: f8f5f8e3 bgeu a1,a5,624 + putch('%', putdat); + 698: 00048593 mv a1,s1 + 69c: 02500513 li a0,37 + 6a0: 000900e7 jalr s2 + fmt = last_fmt; + 6a4: 000d8413 mv s0,s11 + break; + 6a8: f45ff06f j 5ec + ch = *fmt; + 6ac: 00174683 lbu a3,1(a4) + switch (ch = *(unsigned char *) fmt++) { + 6b0: 00040713 mv a4,s0 + goto reswitch; + 6b4: f61ff06f j 614 + ch = *fmt; + 6b8: 00174603 lbu a2,1(a4) + precision = precision * 10 + ch - '0'; + 6bc: fd068d13 addi s10,a3,-48 + switch (ch = *(unsigned char *) fmt++) { + 6c0: 00040713 mv a4,s0 + if (ch < '0' || ch > '9') + 6c4: fd060793 addi a5,a2,-48 + ch = *fmt; + 6c8: 00060693 mv a3,a2 + if (ch < '0' || ch > '9') + 6cc: 02f56663 bltu a0,a5,6f8 + precision = precision * 10 + ch - '0'; + 6d0: 002d1793 slli a5,s10,0x2 + 6d4: 01a787b3 add a5,a5,s10 + for (precision = 0; ; ++fmt) { + 6d8: 00170713 addi a4,a4,1 + precision = precision * 10 + ch - '0'; + 6dc: 00179793 slli a5,a5,0x1 + 6e0: 00c787b3 add a5,a5,a2 + ch = *fmt; + 6e4: 00074603 lbu a2,0(a4) + precision = precision * 10 + ch - '0'; + 6e8: fd078d13 addi s10,a5,-48 + if (ch < '0' || ch > '9') + 6ec: fd060793 addi a5,a2,-48 + ch = *fmt; + 6f0: 00060693 mv a3,a2 + if (ch < '0' || ch > '9') + 6f4: fcf57ee3 bgeu a0,a5,6d0 + if (width < 0) + 6f8: f00b5ee3 bgez s6,614 + width = precision, precision = -1; + 6fc: 000d0b13 mv s6,s10 + 700: fff00d13 li s10,-1 + 704: f11ff06f j 614 + putch(ch, putdat); + 708: 00048593 mv a1,s1 + 70c: 02500513 li a0,37 + 710: 000900e7 jalr s2 + break; + 714: ed9ff06f j 5ec + precision = va_arg(ap, int); + 718: 00012783 lw a5,0(sp) + ch = *fmt; + 71c: 00174683 lbu a3,1(a4) + switch (ch = *(unsigned char *) fmt++) { + 720: 00040713 mv a4,s0 + precision = va_arg(ap, int); + 724: 0007ad03 lw s10,0(a5) + 728: 00478793 addi a5,a5,4 + 72c: 00f12023 sw a5,0(sp) + goto process_precision; + 730: fc9ff06f j 6f8 + switch (ch = *(unsigned char *) fmt++) { + 734: 01000a93 li s5,16 + return va_arg(*ap, unsigned int); + 738: 00012783 lw a5,0(sp) + 73c: 0007ac03 lw s8,0(a5) + 740: 00478793 addi a5,a5,4 + 744: 00f12023 sw a5,0(sp) + digs[pos++] = num % base; + 748: 000a8593 mv a1,s5 + 74c: 000c0513 mv a0,s8 + 750: 491000ef jal ra,13e0 <__umodsi3> + 754: 02a12823 sw a0,48(sp) + 758: 00050d13 mv s10,a0 + 75c: 03410a13 addi s4,sp,52 + 760: 00100c93 li s9,1 + if (num < base) + 764: 355c6e63 bltu s8,s5,ac0 <__stack_size+0x2c0> + num /= base; + 768: 000a8593 mv a1,s5 + 76c: 000c0513 mv a0,s8 + 770: 429000ef jal ra,1398 <__udivsi3> + digs[pos++] = num % base; + 774: 000a8593 mv a1,s5 + num /= base; + 778: 00050c13 mv s8,a0 + digs[pos++] = num % base; + 77c: 465000ef jal ra,13e0 <__umodsi3> + 780: 00aa2023 sw a0,0(s4) + 784: 000c8d93 mv s11,s9 + 788: 00050d13 mv s10,a0 + if (num < base) + 78c: 004a0a13 addi s4,s4,4 + digs[pos++] = num % base; + 790: 001c8c93 addi s9,s9,1 # 80000001 + if (num < base) + 794: fd5c7ae3 bgeu s8,s5,768 + while (width-- > pos) + 798: 016cdc63 bge s9,s6,7b0 + 79c: fffb0b13 addi s6,s6,-1 + putch(padc, putdat); + 7a0: 00048593 mv a1,s1 + 7a4: 000b8513 mv a0,s7 + 7a8: 000900e7 jalr s2 + while (width-- > pos) + 7ac: ff6cc8e3 blt s9,s6,79c + 7b0: 00412783 lw a5,4(sp) + 7b4: 02c10b93 addi s7,sp,44 + putch(digs[pos] + (digs[pos] >= 10 ? 'a' - 10 : '0'), putdat); + 7b8: 00900b13 li s6,9 + 7bc: 00fd8db3 add s11,s11,a5 + 7c0: 002d9d93 slli s11,s11,0x2 + 7c4: 03010793 addi a5,sp,48 + 7c8: 01b78db3 add s11,a5,s11 + 7cc: 00c0006f j 7d8 + 7d0: 000dad03 lw s10,0(s11) + 7d4: ffcd8d93 addi s11,s11,-4 + 7d8: 01ab37b3 sltu a5,s6,s10 + 7dc: 40f007b3 neg a5,a5 + 7e0: 0277f793 andi a5,a5,39 + 7e4: 03078793 addi a5,a5,48 + 7e8: 00048593 mv a1,s1 + 7ec: 01a78533 add a0,a5,s10 + 7f0: 000900e7 jalr s2 + while (pos-- > 0) + 7f4: fdbb9ee3 bne s7,s11,7d0 + 7f8: df5ff06f j 5ec + if ((p = va_arg(ap, char *)) == NULL) + 7fc: 00012783 lw a5,0(sp) + 800: 0007ad83 lw s11,0(a5) + 804: 00478a13 addi s4,a5,4 + 808: 2e0d8c63 beqz s11,b00 <__stack_size+0x300> + if (width > 0 && padc != '-') + 80c: 0b605263 blez s6,8b0 <__stack_size+0xb0> + 810: 02d00793 li a5,45 + 814: 04fb9e63 bne s7,a5,870 <__stack_size+0x70> + for (; (ch = *p) != '\0' && (precision < 0 || --precision >= 0); width--) { + 818: 000dc503 lbu a0,0(s11) + 81c: 02050863 beqz a0,84c <__stack_size+0x4c> + 820: fff00b93 li s7,-1 + 824: 000d4663 bltz s10,830 <__stack_size+0x30> + 828: fffd0d13 addi s10,s10,-1 + 82c: 017d0e63 beq s10,s7,848 <__stack_size+0x48> + putch(ch, putdat); + 830: 00048593 mv a1,s1 + p++; + 834: 001d8d93 addi s11,s11,1 + putch(ch, putdat); + 838: 000900e7 jalr s2 + for (; (ch = *p) != '\0' && (precision < 0 || --precision >= 0); width--) { + 83c: 000dc503 lbu a0,0(s11) + 840: fffb0b13 addi s6,s6,-1 + 844: fe0510e3 bnez a0,824 <__stack_size+0x24> + for (; width > 0; width--) + 848: 01605c63 blez s6,860 <__stack_size+0x60> + 84c: fffb0b13 addi s6,s6,-1 + putch(' ', putdat); + 850: 00048593 mv a1,s1 + 854: 02000513 li a0,32 + 858: 000900e7 jalr s2 + for (; width > 0; width--) + 85c: fe0b18e3 bnez s6,84c <__stack_size+0x4c> + if ((p = va_arg(ap, char *)) == NULL) + 860: 01412023 sw s4,0(sp) + 864: d89ff06f j 5ec + p = "(null)"; + 868: 00001d97 auipc s11,0x1 + 86c: c90d8d93 addi s11,s11,-880 # 14f8 <__clzsi2+0xb4> + while (n-- > 0 && *str) str++; + 870: 000d8793 mv a5,s11 + 874: 01ad86b3 add a3,s11,s10 + 878: 000d1863 bnez s10,888 <__stack_size+0x88> + 87c: 0200006f j 89c <__stack_size+0x9c> + 880: 00178793 addi a5,a5,1 + 884: 00d78663 beq a5,a3,890 <__stack_size+0x90> + 888: 0007c703 lbu a4,0(a5) + 88c: fe071ae3 bnez a4,880 <__stack_size+0x80> + return str - start; + 890: 41b787b3 sub a5,a5,s11 + for (width -= strnlen(p, precision); width > 0; width--) + 894: 40fb0b33 sub s6,s6,a5 + 898: 01605c63 blez s6,8b0 <__stack_size+0xb0> + 89c: fffb0b13 addi s6,s6,-1 + putch(padc, putdat); + 8a0: 00048593 mv a1,s1 + 8a4: 000b8513 mv a0,s7 + 8a8: 000900e7 jalr s2 + for (width -= strnlen(p, precision); width > 0; width--) + 8ac: fe0b18e3 bnez s6,89c <__stack_size+0x9c> + for (; (ch = *p) != '\0' && (precision < 0 || --precision >= 0); width--) { + 8b0: 000dc503 lbu a0,0(s11) + 8b4: fa0506e3 beqz a0,860 <__stack_size+0x60> + 8b8: fff00b93 li s7,-1 + 8bc: f69ff06f j 824 <__stack_size+0x24> + putch(va_arg(ap, int), putdat); + 8c0: 00012783 lw a5,0(sp) + 8c4: 00048593 mv a1,s1 + 8c8: 0007a503 lw a0,0(a5) + 8cc: 00478a13 addi s4,a5,4 + 8d0: 000900e7 jalr s2 + 8d4: 01412023 sw s4,0(sp) + break; + 8d8: d15ff06f j 5ec + return va_arg(*ap, int); + 8dc: 00012783 lw a5,0(sp) + 8e0: 0007ac03 lw s8,0(a5) + 8e4: 00478a13 addi s4,a5,4 + if ((long) num < 0) { + 8e8: 000c5a63 bgez s8,8fc <__stack_size+0xfc> + putch('-', putdat); + 8ec: 00048593 mv a1,s1 + 8f0: 02d00513 li a0,45 + 8f4: 000900e7 jalr s2 + num = -(long) num; + 8f8: 41800c33 neg s8,s8 + return va_arg(*ap, int); + 8fc: 01412023 sw s4,0(sp) + num = -(long) num; + 900: 00a00a93 li s5,10 + 904: e45ff06f j 748 + print_double(putch, putdat, va_arg(ap, double), width, precision); + 908: 00012783 lw a5,0(sp) + 90c: 00778a13 addi s4,a5,7 + 910: ff8a7a13 andi s4,s4,-8 + 914: 004a2d83 lw s11,4(s4) + 918: 000a2a83 lw s5,0(s4) + 91c: 008a0793 addi a5,s4,8 + 920: 00f12023 sw a5,0(sp) + u.d = num; + 924: 000d8713 mv a4,s11 + 928: 000a8693 mv a3,s5 + if (u.u & (1ULL << 63)) { + 92c: 1a0dc063 bltz s11,acc <__stack_size+0x2cc> + for (int i = 0; i < prec; i++) + 930: 05a05263 blez s10,974 <__stack_size+0x174> + 934: 0ffff797 auipc a5,0xffff + 938: 6cc78793 addi a5,a5,1740 # 10000000 <_data> + u.d *= 10; + 93c: 0007ab03 lw s6,0(a5) + 940: 0047ab83 lw s7,4(a5) + for (int i = 0; i < prec; i++) + 944: 00000a13 li s4,0 + u.d *= 10; + 948: 00068513 mv a0,a3 + 94c: 00070593 mv a1,a4 + 950: 000b8693 mv a3,s7 + 954: 000b0613 mv a2,s6 + 958: 2cc000ef jal ra,c24 <__muldf3> + for (int i = 0; i < prec; i++) + 95c: 001a0a13 addi s4,s4,1 + u.d *= 10; + 960: 00050a93 mv s5,a0 + 964: 00058d93 mv s11,a1 + 968: 00050693 mv a3,a0 + 96c: 00058713 mv a4,a1 + for (int i = 0; i < prec; i++) + 970: fd4d1ce3 bne s10,s4,948 <__stack_size+0x148> + printnum(sprintf_putch, (void**)&pbuf, (unsigned long)u.d, 10, 0, 0); + 974: 000d8593 mv a1,s11 + 978: 000a8513 mv a0,s5 + 97c: 175000ef jal ra,12f0 <__fixunsdfsi> + digs[pos++] = num % base; + 980: 00a00593 li a1,10 + printnum(sprintf_putch, (void**)&pbuf, (unsigned long)u.d, 10, 0, 0); + 984: 00050b13 mv s6,a0 + digs[pos++] = num % base; + 988: 259000ef jal ra,13e0 <__umodsi3> + 98c: 02a12823 sw a0,48(sp) + if (num < base) + 990: 00900793 li a5,9 + 994: 1967f663 bgeu a5,s6,b20 <__stack_size+0x320> + 998: 03410a13 addi s4,sp,52 + digs[pos++] = num % base; + 99c: 00100d93 li s11,1 + if (num < base) + 9a0: 06300b93 li s7,99 + num /= base; + 9a4: 00a00593 li a1,10 + 9a8: 000b0513 mv a0,s6 + 9ac: 1ed000ef jal ra,1398 <__udivsi3> + digs[pos++] = num % base; + 9b0: 00a00593 li a1,10 + 9b4: 000b0a93 mv s5,s6 + num /= base; + 9b8: 00050b13 mv s6,a0 + digs[pos++] = num % base; + 9bc: 225000ef jal ra,13e0 <__umodsi3> + 9c0: 00aa2023 sw a0,0(s4) + 9c4: 000d8613 mv a2,s11 + if (num < base) + 9c8: 004a0a13 addi s4,s4,4 + digs[pos++] = num % base; + 9cc: 001d8d93 addi s11,s11,1 + if (num < base) + 9d0: fd5beae3 bltu s7,s5,9a4 <__stack_size+0x1a4> + 9d4: 03010813 addi a6,sp,48 + 9d8: 00261713 slli a4,a2,0x2 + 9dc: 00e80733 add a4,a6,a4 + putch(digs[pos] + (digs[pos] >= 10 ? 'a' - 10 : '0'), putdat); + 9e0: 01010693 addi a3,sp,16 + 9e4: 00900893 li a7,9 + 9e8: 00c0006f j 9f4 <__stack_size+0x1f4> + 9ec: ffc72503 lw a0,-4(a4) + 9f0: 00058713 mv a4,a1 + 9f4: 00a8b7b3 sltu a5,a7,a0 + 9f8: 40f007b3 neg a5,a5 + 9fc: 0277f793 andi a5,a5,39 + a00: 03078793 addi a5,a5,48 + a04: 00a787b3 add a5,a5,a0 + **pstr = ch; + a08: 0ff7f793 zext.b a5,a5 + a0c: 00f68023 sb a5,0(a3) + while (pos-- > 0) + a10: ffc70593 addi a1,a4,-4 + (*pstr)++; + a14: 00168693 addi a3,a3,1 + while (pos-- > 0) + a18: fce81ae3 bne a6,a4,9ec <__stack_size+0x1ec> + (*pstr)++; + a1c: 01160713 addi a4,a2,17 + a20: 00270bb3 add s7,a4,sp + if (prec > 0) { + a24: 03a05a63 blez s10,a58 <__stack_size+0x258> + a28: 000b8713 mv a4,s7 + a2c: 41ab86b3 sub a3,s7,s10 + a30: 0080006f j a38 <__stack_size+0x238> + pbuf[-i] = pbuf[-i-1]; + a34: fff74783 lbu a5,-1(a4) + a38: 00f70023 sb a5,0(a4) + for (int i = 0; i < prec; i++) { + a3c: fff70713 addi a4,a4,-1 + a40: fed71ae3 bne a4,a3,a34 <__stack_size+0x234> + pbuf[-prec] = '.'; + a44: 41ab8bb3 sub s7,s7,s10 + a48: 02e00793 li a5,46 + a4c: 00fb8023 sb a5,0(s7) + pbuf++; + a50: 01260793 addi a5,a2,18 + a54: 00278bb3 add s7,a5,sp + for (char* p = buf; p < pbuf; p++) + a58: 01010b13 addi s6,sp,16 + a5c: b97b78e3 bgeu s6,s7,5ec + putch(*p, putdat); + a60: 000b4503 lbu a0,0(s6) + a64: 00048593 mv a1,s1 + for (char* p = buf; p < pbuf; p++) + a68: 001b0b13 addi s6,s6,1 + putch(*p, putdat); + a6c: 000900e7 jalr s2 + for (char* p = buf; p < pbuf; p++) + a70: ff7b18e3 bne s6,s7,a60 <__stack_size+0x260> + a74: b79ff06f j 5ec + putch('0', putdat); + a78: 03000513 li a0,48 + a7c: 00048593 mv a1,s1 + a80: 000900e7 jalr s2 + putch('x', putdat); + a84: 00048593 mv a1,s1 + a88: 07800513 li a0,120 + a8c: 000900e7 jalr s2 + return va_arg(*ap, unsigned long); + a90: 00012783 lw a5,0(sp) + a94: 01000a93 li s5,16 + a98: 00478793 addi a5,a5,4 + a9c: 00f12023 sw a5,0(sp) + aa0: ffc7ac03 lw s8,-4(a5) + aa4: ca5ff06f j 748 + if (width < 0) + aa8: fffb4793 not a5,s6 + aac: 41f7d793 srai a5,a5,0x1f + ch = *fmt; + ab0: 00174683 lbu a3,1(a4) + ab4: 00fb7b33 and s6,s6,a5 + switch (ch = *(unsigned char *) fmt++) { + ab8: 00040713 mv a4,s0 + goto reswitch; + abc: b59ff06f j 614 + while (width-- > pos) + ac0: 00000d93 li s11,0 + ac4: cd6ccce3 blt s9,s6,79c + ac8: ce9ff06f j 7b0 + putch('-', putdat); + acc: 00048593 mv a1,s1 + ad0: 02d00513 li a0,45 + ad4: 01512623 sw s5,12(sp) + ad8: 000900e7 jalr s2 + u.u &= ~(1ULL << 63); + adc: 00812783 lw a5,8(sp) + printnum(sprintf_putch, (void**)&pbuf, (unsigned long)u.d, 10, 0, 0); + ae0: 00c12683 lw a3,12(sp) + u.u &= ~(1ULL << 63); + ae4: 01b7f733 and a4,a5,s11 + printnum(sprintf_putch, (void**)&pbuf, (unsigned long)u.d, 10, 0, 0); + ae8: 00070d93 mv s11,a4 + aec: e45ff06f j 930 <__stack_size+0x130> + switch (ch = *(unsigned char *) fmt++) { + af0: 00800a93 li s5,8 + af4: c45ff06f j 738 + af8: 00a00a93 li s5,10 + afc: c3dff06f j 738 + if (width > 0 && padc != '-') + b00: 01605663 blez s6,b0c <__stack_size+0x30c> + b04: 02d00793 li a5,45 + b08: d6fb90e3 bne s7,a5,868 <__stack_size+0x68> + b0c: 00001d97 auipc s11,0x1 + b10: 9ecd8d93 addi s11,s11,-1556 # 14f8 <__clzsi2+0xb4> + for (; (ch = *p) != '\0' && (precision < 0 || --precision >= 0); width--) { + b14: 02800513 li a0,40 + b18: fff00b93 li s7,-1 + b1c: d09ff06f j 824 <__stack_size+0x24> + while (pos-- > 0) + b20: 00000613 li a2,0 + b24: eb1ff06f j 9d4 <__stack_size+0x1d4> + +00000b28 : + while (n-- > 0 && *str) str++; + b28: 00b506b3 add a3,a0,a1 + b2c: 00050793 mv a5,a0 + b30: 00059863 bnez a1,b40 + b34: 0240006f j b58 + b38: 00178793 addi a5,a5,1 + b3c: 00f68a63 beq a3,a5,b50 + b40: 0007c703 lbu a4,0(a5) + b44: fe071ae3 bnez a4,b38 + return str - start; + b48: 40a78533 sub a0,a5,a0 +} + b4c: 00008067 ret + return str - start; + b50: 40a68533 sub a0,a3,a0 + b54: 00008067 ret + while (n-- > 0 && *str) str++; + b58: 00000513 li a0,0 + b5c: 00008067 ret + +00000b60 <__wrap_printf>: + +int __wrap_printf(const char* fmt, ...) +{ + b60: fc010113 addi sp,sp,-64 + va_list ap; + va_start(ap, fmt); + b64: 02410313 addi t1,sp,36 +{ + b68: 00050e13 mv t3,a0 + b6c: 02b12223 sw a1,36(sp) + b70: 02c12423 sw a2,40(sp) + b74: 02d12623 sw a3,44(sp) + + vprintfmt((void*)putchar, 0, fmt, ap); + b78: 00000517 auipc a0,0x0 + b7c: 9c050513 addi a0,a0,-1600 # 538 + b80: 00030693 mv a3,t1 + b84: 000e0613 mv a2,t3 + b88: 00000593 li a1,0 +{ + b8c: 00112e23 sw ra,28(sp) + b90: 02e12823 sw a4,48(sp) + b94: 02f12a23 sw a5,52(sp) + b98: 03012c23 sw a6,56(sp) + b9c: 03112e23 sw a7,60(sp) + va_start(ap, fmt); + ba0: 00612623 sw t1,12(sp) + vprintfmt((void*)putchar, 0, fmt, ap); + ba4: 9d1ff0ef jal ra,574 + + va_end(ap); + return 0; // incorrect return value, but who cares, anyway? +} + ba8: 01c12083 lw ra,28(sp) + bac: 00000513 li a0,0 + bb0: 04010113 addi sp,sp,64 + bb4: 00008067 ret + +00000bb8 <__wrap_sprintf>: + +int __wrap_sprintf(char* str, const char* fmt, ...) +{ + bb8: fb010113 addi sp,sp,-80 + va_list ap; + char* str0 = str; + va_start(ap, fmt); + bbc: 03810313 addi t1,sp,56 +{ + bc0: 02812423 sw s0,40(sp) + bc4: 00a12623 sw a0,12(sp) + bc8: 02c12c23 sw a2,56(sp) + bcc: 02d12e23 sw a3,60(sp) + char* str0 = str; + bd0: 00050413 mv s0,a0 + + vprintfmt(sprintf_putch, (void**)&str, fmt, ap); + bd4: 00058613 mv a2,a1 + bd8: 00000517 auipc a0,0x0 + bdc: 94850513 addi a0,a0,-1720 # 520 + be0: 00c10593 addi a1,sp,12 + be4: 00030693 mv a3,t1 +{ + be8: 02112623 sw ra,44(sp) + bec: 04f12223 sw a5,68(sp) + bf0: 04e12023 sw a4,64(sp) + bf4: 05012423 sw a6,72(sp) + bf8: 05112623 sw a7,76(sp) + va_start(ap, fmt); + bfc: 00612e23 sw t1,28(sp) + vprintfmt(sprintf_putch, (void**)&str, fmt, ap); + c00: 975ff0ef jal ra,574 + *str = 0; + c04: 00c12783 lw a5,12(sp) + c08: 00078023 sb zero,0(a5) + + va_end(ap); + return str - str0; + c0c: 00c12503 lw a0,12(sp) +} + c10: 02c12083 lw ra,44(sp) + c14: 40850533 sub a0,a0,s0 + c18: 02812403 lw s0,40(sp) + c1c: 05010113 addi sp,sp,80 + c20: 00008067 ret + +00000c24 <__muldf3>: +#include "soft-fp.h" +#include "double.h" + +DFtype +__muldf3 (DFtype a, DFtype b) +{ + c24: fd010113 addi sp,sp,-48 + c28: 01312e23 sw s3,28(sp) + FP_DECL_D (B); + FP_DECL_D (R); + DFtype r; + + FP_INIT_ROUNDMODE; + FP_UNPACK_D (A, a); + c2c: 0145d993 srli s3,a1,0x14 +{ + c30: 02812423 sw s0,40(sp) + c34: 02912223 sw s1,36(sp) + c38: 01412c23 sw s4,24(sp) + c3c: 01512a23 sw s5,20(sp) + c40: 01712623 sw s7,12(sp) + FP_UNPACK_D (A, a); + c44: 00c59493 slli s1,a1,0xc +{ + c48: 02112623 sw ra,44(sp) + c4c: 03212023 sw s2,32(sp) + c50: 01612823 sw s6,16(sp) + FP_UNPACK_D (A, a); + c54: 7ff9f993 andi s3,s3,2047 +{ + c58: 00050413 mv s0,a0 + c5c: 00060b93 mv s7,a2 + c60: 00068a13 mv s4,a3 + FP_UNPACK_D (A, a); + c64: 00c4d493 srli s1,s1,0xc + c68: 01f5da93 srli s5,a1,0x1f + c6c: 3c098863 beqz s3,103c <__muldf3+0x418> + c70: 7ff00793 li a5,2047 + c74: 42f98663 beq s3,a5,10a0 <__muldf3+0x47c> + c78: 00349493 slli s1,s1,0x3 + c7c: 01d55793 srli a5,a0,0x1d + c80: 0097e7b3 or a5,a5,s1 + c84: 008004b7 lui s1,0x800 + c88: 0097e4b3 or s1,a5,s1 + c8c: 00351913 slli s2,a0,0x3 + c90: c0198993 addi s3,s3,-1023 + c94: 00000b13 li s6,0 + FP_UNPACK_D (B, b); + c98: 014a5713 srli a4,s4,0x14 + c9c: 00ca1413 slli s0,s4,0xc + ca0: 7ff77713 andi a4,a4,2047 + ca4: 00c45413 srli s0,s0,0xc + ca8: 01fa5a13 srli s4,s4,0x1f + cac: 42070663 beqz a4,10d8 <__muldf3+0x4b4> + cb0: 7ff00793 li a5,2047 + cb4: 48f70663 beq a4,a5,1140 <__muldf3+0x51c> + cb8: 00341413 slli s0,s0,0x3 + cbc: 01dbd793 srli a5,s7,0x1d + cc0: 0087e7b3 or a5,a5,s0 + cc4: 00800437 lui s0,0x800 + cc8: 0087e433 or s0,a5,s0 + ccc: c0170713 addi a4,a4,-1023 + cd0: 003b9793 slli a5,s7,0x3 + cd4: 00000613 li a2,0 + FP_MUL_D (R, A, B); + cd8: 00e989b3 add s3,s3,a4 + cdc: 002b1713 slli a4,s6,0x2 + ce0: 00c76733 or a4,a4,a2 + ce4: 00a00693 li a3,10 + ce8: 014ac833 xor a6,s5,s4 + cec: 00198893 addi a7,s3,1 + cf0: 4ce6c863 blt a3,a4,11c0 <__muldf3+0x59c> + cf4: 00200693 li a3,2 + cf8: 48e6c063 blt a3,a4,1178 <__muldf3+0x554> + cfc: fff70713 addi a4,a4,-1 + d00: 00100693 li a3,1 + d04: 48e6fc63 bgeu a3,a4,119c <__muldf3+0x578> + d08: 00010a37 lui s4,0x10 + d0c: fffa0393 addi t2,s4,-1 # ffff <_data_lma+0xe8a7> + d10: 0107d293 srli t0,a5,0x10 + d14: 00797e33 and t3,s2,t2 + d18: 0077f7b3 and a5,a5,t2 + d1c: 01095f93 srli t6,s2,0x10 + d20: 000e0513 mv a0,t3 + d24: 00078593 mv a1,a5 + d28: 644000ef jal ra,136c <__mulsi3> + d2c: 00050e93 mv t4,a0 + d30: 00028593 mv a1,t0 + d34: 000e0513 mv a0,t3 + d38: 634000ef jal ra,136c <__mulsi3> + d3c: 00050713 mv a4,a0 + d40: 00078593 mv a1,a5 + d44: 000f8513 mv a0,t6 + d48: 624000ef jal ra,136c <__mulsi3> + d4c: 00050913 mv s2,a0 + d50: 00028593 mv a1,t0 + d54: 000f8513 mv a0,t6 + d58: 614000ef jal ra,136c <__mulsi3> + d5c: 010ed313 srli t1,t4,0x10 + d60: 01270733 add a4,a4,s2 + d64: 00e30333 add t1,t1,a4 + d68: 00050f13 mv t5,a0 + d6c: 01237463 bgeu t1,s2,d74 <__muldf3+0x150> + d70: 01450f33 add t5,a0,s4 + d74: 01035913 srli s2,t1,0x10 + d78: 00737333 and t1,t1,t2 + d7c: 007efeb3 and t4,t4,t2 + d80: 01031313 slli t1,t1,0x10 + d84: 007473b3 and t2,s0,t2 + d88: 01d30333 add t1,t1,t4 + d8c: 01045a13 srli s4,s0,0x10 + d90: 000e0513 mv a0,t3 + d94: 00038593 mv a1,t2 + d98: 5d4000ef jal ra,136c <__mulsi3> + d9c: 00050e93 mv t4,a0 + da0: 000a0593 mv a1,s4 + da4: 000e0513 mv a0,t3 + da8: 5c4000ef jal ra,136c <__mulsi3> + dac: 00050e13 mv t3,a0 + db0: 00038593 mv a1,t2 + db4: 000f8513 mv a0,t6 + db8: 5b4000ef jal ra,136c <__mulsi3> + dbc: 00050413 mv s0,a0 + dc0: 000a0593 mv a1,s4 + dc4: 000f8513 mv a0,t6 + dc8: 5a4000ef jal ra,136c <__mulsi3> + dcc: 010ed713 srli a4,t4,0x10 + dd0: 008e0e33 add t3,t3,s0 + dd4: 01c70733 add a4,a4,t3 + dd8: 00050693 mv a3,a0 + ddc: 00877663 bgeu a4,s0,de8 <__muldf3+0x1c4> + de0: 00010637 lui a2,0x10 + de4: 00c506b3 add a3,a0,a2 + de8: 00010b37 lui s6,0x10 + dec: fffb0e13 addi t3,s6,-1 # ffff <_data_lma+0xe8a7> + df0: 01075f93 srli t6,a4,0x10 + df4: 01c77733 and a4,a4,t3 + df8: 01071713 slli a4,a4,0x10 + dfc: 01cefeb3 and t4,t4,t3 + e00: 01d70eb3 add t4,a4,t4 + e04: 01c4fe33 and t3,s1,t3 + e08: 00df8fb3 add t6,t6,a3 + e0c: 01d90933 add s2,s2,t4 + e10: 0104da93 srli s5,s1,0x10 + e14: 000e0513 mv a0,t3 + e18: 00078593 mv a1,a5 + e1c: 550000ef jal ra,136c <__mulsi3> + e20: 00050413 mv s0,a0 + e24: 00028593 mv a1,t0 + e28: 000e0513 mv a0,t3 + e2c: 540000ef jal ra,136c <__mulsi3> + e30: 00050493 mv s1,a0 + e34: 00078593 mv a1,a5 + e38: 000a8513 mv a0,s5 + e3c: 530000ef jal ra,136c <__mulsi3> + e40: 00050b93 mv s7,a0 + e44: 00028593 mv a1,t0 + e48: 000a8513 mv a0,s5 + e4c: 520000ef jal ra,136c <__mulsi3> + e50: 01045793 srli a5,s0,0x10 + e54: 017484b3 add s1,s1,s7 + e58: 009787b3 add a5,a5,s1 + e5c: 00050713 mv a4,a0 + e60: 0177f463 bgeu a5,s7,e68 <__muldf3+0x244> + e64: 01650733 add a4,a0,s6 + e68: 000104b7 lui s1,0x10 + e6c: fff48693 addi a3,s1,-1 # ffff <_data_lma+0xe8a7> + e70: 0107d293 srli t0,a5,0x10 + e74: 00e282b3 add t0,t0,a4 + e78: 00d7f733 and a4,a5,a3 + e7c: 00d47433 and s0,s0,a3 + e80: 01071713 slli a4,a4,0x10 + e84: 00870733 add a4,a4,s0 + e88: 000e0513 mv a0,t3 + e8c: 00038593 mv a1,t2 + e90: 4dc000ef jal ra,136c <__mulsi3> + e94: 00050413 mv s0,a0 + e98: 000a0593 mv a1,s4 + e9c: 000e0513 mv a0,t3 + ea0: 4cc000ef jal ra,136c <__mulsi3> + ea4: 00050e13 mv t3,a0 + ea8: 00038593 mv a1,t2 + eac: 000a8513 mv a0,s5 + eb0: 4bc000ef jal ra,136c <__mulsi3> + eb4: 00050393 mv t2,a0 + eb8: 000a0593 mv a1,s4 + ebc: 000a8513 mv a0,s5 + ec0: 4ac000ef jal ra,136c <__mulsi3> + ec4: 01045793 srli a5,s0,0x10 + ec8: 007e0e33 add t3,t3,t2 + ecc: 01c78e33 add t3,a5,t3 + ed0: 00050593 mv a1,a0 + ed4: 007e7463 bgeu t3,t2,edc <__muldf3+0x2b8> + ed8: 009505b3 add a1,a0,s1 + edc: 000106b7 lui a3,0x10 + ee0: fff68693 addi a3,a3,-1 # ffff <_data_lma+0xe8a7> + ee4: 00de77b3 and a5,t3,a3 + ee8: 00d47433 and s0,s0,a3 + eec: 01079793 slli a5,a5,0x10 + ef0: 012f0f33 add t5,t5,s2 + ef4: 008787b3 add a5,a5,s0 + ef8: 01df3eb3 sltu t4,t5,t4 + efc: 01f787b3 add a5,a5,t6 + f00: 01d78533 add a0,a5,t4 + f04: 00ef0f33 add t5,t5,a4 + f08: 00ef3733 sltu a4,t5,a4 + f0c: 005506b3 add a3,a0,t0 + f10: 00e68633 add a2,a3,a4 + f14: 01f7b433 sltu s0,a5,t6 + f18: 01d53533 sltu a0,a0,t4 + f1c: 010e5793 srli a5,t3,0x10 + f20: 00e63733 sltu a4,a2,a4 + f24: 00a46433 or s0,s0,a0 + f28: 0056b6b3 sltu a3,a3,t0 + f2c: 00f40433 add s0,s0,a5 + f30: 00e6e6b3 or a3,a3,a4 + f34: 00d40433 add s0,s0,a3 + f38: 00b40433 add s0,s0,a1 + f3c: 01765793 srli a5,a2,0x17 + f40: 00941413 slli s0,s0,0x9 + f44: 00f46433 or s0,s0,a5 + f48: 009f1793 slli a5,t5,0x9 + f4c: 0067e7b3 or a5,a5,t1 + f50: 00f037b3 snez a5,a5 + f54: 017f5f13 srli t5,t5,0x17 + f58: 00961713 slli a4,a2,0x9 + f5c: 01e7e7b3 or a5,a5,t5 + f60: 00e7e7b3 or a5,a5,a4 + f64: 01000737 lui a4,0x1000 + f68: 00e47733 and a4,s0,a4 + f6c: 28070663 beqz a4,11f8 <__muldf3+0x5d4> + f70: 0017d713 srli a4,a5,0x1 + f74: 0017f793 andi a5,a5,1 + f78: 00f76733 or a4,a4,a5 + f7c: 01f41793 slli a5,s0,0x1f + f80: 00f767b3 or a5,a4,a5 + f84: 00145413 srli s0,s0,0x1 + FP_PACK_D (r, R); + f88: 3ff88693 addi a3,a7,1023 + f8c: 26d05a63 blez a3,1200 <__muldf3+0x5dc> + f90: 0077f713 andi a4,a5,7 + f94: 02070063 beqz a4,fb4 <__muldf3+0x390> + f98: 00f7f713 andi a4,a5,15 + f9c: 00400613 li a2,4 + fa0: 00c70a63 beq a4,a2,fb4 <__muldf3+0x390> + fa4: 00478713 addi a4,a5,4 + fa8: 00f737b3 sltu a5,a4,a5 + fac: 00f40433 add s0,s0,a5 + fb0: 00070793 mv a5,a4 + fb4: 01000737 lui a4,0x1000 + fb8: 00e47733 and a4,s0,a4 + fbc: 00070a63 beqz a4,fd0 <__muldf3+0x3ac> + fc0: ff000737 lui a4,0xff000 + fc4: fff70713 addi a4,a4,-1 # feffffff + fc8: 00e47433 and s0,s0,a4 + fcc: 40088693 addi a3,a7,1024 + fd0: 7fe00713 li a4,2046 + fd4: 2ed74e63 blt a4,a3,12d0 <__muldf3+0x6ac> + fd8: 01d41713 slli a4,s0,0x1d + fdc: 0037d793 srli a5,a5,0x3 + fe0: 00f76733 or a4,a4,a5 + fe4: 00345413 srli s0,s0,0x3 + fe8: 7ff007b7 lui a5,0x7ff00 + fec: 01469693 slli a3,a3,0x14 + ff0: 00c41413 slli s0,s0,0xc + ff4: 00f6f6b3 and a3,a3,a5 + ff8: 00c45413 srli s0,s0,0xc + FP_HANDLE_EXCEPTIONS; + + return r; +} + ffc: 02c12083 lw ra,44(sp) + FP_PACK_D (r, R); + 1000: 0086e6b3 or a3,a3,s0 +} + 1004: 02812403 lw s0,40(sp) + FP_PACK_D (r, R); + 1008: 01f81813 slli a6,a6,0x1f + 100c: 0106e7b3 or a5,a3,a6 +} + 1010: 02412483 lw s1,36(sp) + 1014: 02012903 lw s2,32(sp) + 1018: 01c12983 lw s3,28(sp) + 101c: 01812a03 lw s4,24(sp) + 1020: 01412a83 lw s5,20(sp) + 1024: 01012b03 lw s6,16(sp) + 1028: 00c12b83 lw s7,12(sp) + 102c: 00070513 mv a0,a4 + 1030: 00078593 mv a1,a5 + 1034: 03010113 addi sp,sp,48 + 1038: 00008067 ret + FP_UNPACK_D (A, a); + 103c: 00a4e933 or s2,s1,a0 + 1040: 06090c63 beqz s2,10b8 <__muldf3+0x494> + 1044: 04048063 beqz s1,1084 <__muldf3+0x460> + 1048: 00048513 mv a0,s1 + 104c: 3f8000ef jal ra,1444 <__clzsi2> + 1050: ff550713 addi a4,a0,-11 + 1054: 01c00793 li a5,28 + 1058: 02e7cc63 blt a5,a4,1090 <__muldf3+0x46c> + 105c: 01d00793 li a5,29 + 1060: ff850913 addi s2,a0,-8 + 1064: 40e787b3 sub a5,a5,a4 + 1068: 012494b3 sll s1,s1,s2 + 106c: 00f457b3 srl a5,s0,a5 + 1070: 0097e4b3 or s1,a5,s1 + 1074: 01241933 sll s2,s0,s2 + 1078: c0d00993 li s3,-1011 + 107c: 40a989b3 sub s3,s3,a0 + 1080: c15ff06f j c94 <__muldf3+0x70> + 1084: 3c0000ef jal ra,1444 <__clzsi2> + 1088: 02050513 addi a0,a0,32 + 108c: fc5ff06f j 1050 <__muldf3+0x42c> + 1090: fd850493 addi s1,a0,-40 + 1094: 009414b3 sll s1,s0,s1 + 1098: 00000913 li s2,0 + 109c: fddff06f j 1078 <__muldf3+0x454> + 10a0: 00a4e933 or s2,s1,a0 + 10a4: 02090263 beqz s2,10c8 <__muldf3+0x4a4> + 10a8: 00050913 mv s2,a0 + 10ac: 7ff00993 li s3,2047 + 10b0: 00300b13 li s6,3 + 10b4: be5ff06f j c98 <__muldf3+0x74> + 10b8: 00000493 li s1,0 + 10bc: 00000993 li s3,0 + 10c0: 00100b13 li s6,1 + 10c4: bd5ff06f j c98 <__muldf3+0x74> + 10c8: 00000493 li s1,0 + 10cc: 7ff00993 li s3,2047 + 10d0: 00200b13 li s6,2 + 10d4: bc5ff06f j c98 <__muldf3+0x74> + FP_UNPACK_D (B, b); + 10d8: 017467b3 or a5,s0,s7 + 10dc: 06078e63 beqz a5,1158 <__muldf3+0x534> + 10e0: 04040063 beqz s0,1120 <__muldf3+0x4fc> + 10e4: 00040513 mv a0,s0 + 10e8: 35c000ef jal ra,1444 <__clzsi2> + 10ec: ff550693 addi a3,a0,-11 + 10f0: 01c00793 li a5,28 + 10f4: 02d7ce63 blt a5,a3,1130 <__muldf3+0x50c> + 10f8: 01d00713 li a4,29 + 10fc: ff850793 addi a5,a0,-8 + 1100: 40d70733 sub a4,a4,a3 + 1104: 00f41433 sll s0,s0,a5 + 1108: 00ebd733 srl a4,s7,a4 + 110c: 00876433 or s0,a4,s0 + 1110: 00fb97b3 sll a5,s7,a5 + 1114: c0d00713 li a4,-1011 + 1118: 40a70733 sub a4,a4,a0 + 111c: bb9ff06f j cd4 <__muldf3+0xb0> + 1120: 000b8513 mv a0,s7 + 1124: 320000ef jal ra,1444 <__clzsi2> + 1128: 02050513 addi a0,a0,32 + 112c: fc1ff06f j 10ec <__muldf3+0x4c8> + 1130: fd850413 addi s0,a0,-40 + 1134: 008b9433 sll s0,s7,s0 + 1138: 00000793 li a5,0 + 113c: fd9ff06f j 1114 <__muldf3+0x4f0> + 1140: 017467b3 or a5,s0,s7 + 1144: 02078263 beqz a5,1168 <__muldf3+0x544> + 1148: 000b8793 mv a5,s7 + 114c: 7ff00713 li a4,2047 + 1150: 00300613 li a2,3 + 1154: b85ff06f j cd8 <__muldf3+0xb4> + 1158: 00000413 li s0,0 + 115c: 00000713 li a4,0 + 1160: 00100613 li a2,1 + 1164: b75ff06f j cd8 <__muldf3+0xb4> + 1168: 00000413 li s0,0 + 116c: 7ff00713 li a4,2047 + 1170: 00200613 li a2,2 + 1174: b65ff06f j cd8 <__muldf3+0xb4> + 1178: 00100693 li a3,1 + 117c: 00e696b3 sll a3,a3,a4 + 1180: 5306f713 andi a4,a3,1328 + 1184: 04071863 bnez a4,11d4 <__muldf3+0x5b0> + 1188: 2406f593 andi a1,a3,576 + 118c: 12059463 bnez a1,12b4 <__muldf3+0x690> + 1190: 0886f693 andi a3,a3,136 + 1194: b6068ae3 beqz a3,d08 <__muldf3+0xe4> + 1198: 000a0813 mv a6,s4 + FP_PACK_D (r, R); + 119c: 00200713 li a4,2 + 11a0: 12e60863 beq a2,a4,12d0 <__muldf3+0x6ac> + 11a4: 00300713 li a4,3 + 11a8: 10e60e63 beq a2,a4,12c4 <__muldf3+0x6a0> + 11ac: 00100713 li a4,1 + 11b0: dce61ce3 bne a2,a4,f88 <__muldf3+0x364> + 11b4: 00000413 li s0,0 + 11b8: 00000713 li a4,0 + 11bc: 0bc0006f j 1278 <__muldf3+0x654> + FP_MUL_D (R, A, B); + 11c0: 00f00693 li a3,15 + 11c4: 02d70063 beq a4,a3,11e4 <__muldf3+0x5c0> + 11c8: 00b00693 li a3,11 + 11cc: fcd706e3 beq a4,a3,1198 <__muldf3+0x574> + FP_UNPACK_D (A, a); + 11d0: 000a8813 mv a6,s5 + FP_MUL_D (R, A, B); + 11d4: 00048413 mv s0,s1 + 11d8: 00090793 mv a5,s2 + 11dc: 000b0613 mv a2,s6 + 11e0: fbdff06f j 119c <__muldf3+0x578> + 11e4: 00080437 lui s0,0x80 + 11e8: 00000793 li a5,0 + 11ec: 00000813 li a6,0 + 11f0: 00300613 li a2,3 + 11f4: fb1ff06f j 11a4 <__muldf3+0x580> + 11f8: 00098893 mv a7,s3 + 11fc: d8dff06f j f88 <__muldf3+0x364> + FP_PACK_D (r, R); + 1200: 00100613 li a2,1 + 1204: 40d60633 sub a2,a2,a3 + 1208: 03800713 li a4,56 + 120c: fac744e3 blt a4,a2,11b4 <__muldf3+0x590> + 1210: 01f00713 li a4,31 + 1214: 06c74663 blt a4,a2,1280 <__muldf3+0x65c> + 1218: 41e88893 addi a7,a7,1054 + 121c: 01141733 sll a4,s0,a7 + 1220: 00c7d6b3 srl a3,a5,a2 + 1224: 011798b3 sll a7,a5,a7 + 1228: 00d76733 or a4,a4,a3 + 122c: 011038b3 snez a7,a7 + 1230: 011767b3 or a5,a4,a7 + 1234: 00c45433 srl s0,s0,a2 + 1238: 0077f713 andi a4,a5,7 + 123c: 02070063 beqz a4,125c <__muldf3+0x638> + 1240: 00f7f713 andi a4,a5,15 + 1244: 00400693 li a3,4 + 1248: 00d70a63 beq a4,a3,125c <__muldf3+0x638> + 124c: 00478713 addi a4,a5,4 # 7ff00004 <_sp+0x6fefc004> + 1250: 00f737b3 sltu a5,a4,a5 + 1254: 00f40433 add s0,s0,a5 + 1258: 00070793 mv a5,a4 + 125c: 00800737 lui a4,0x800 + 1260: 00e47733 and a4,s0,a4 + 1264: 06071e63 bnez a4,12e0 <__muldf3+0x6bc> + 1268: 01d41713 slli a4,s0,0x1d + 126c: 0037d793 srli a5,a5,0x3 + 1270: 00f76733 or a4,a4,a5 + 1274: 00345413 srli s0,s0,0x3 + 1278: 00000693 li a3,0 + 127c: d6dff06f j fe8 <__muldf3+0x3c4> + 1280: fe100713 li a4,-31 + 1284: 40d70733 sub a4,a4,a3 + 1288: 02000593 li a1,32 + 128c: 00e45733 srl a4,s0,a4 + 1290: 00000693 li a3,0 + 1294: 00b60663 beq a2,a1,12a0 <__muldf3+0x67c> + 1298: 43e88893 addi a7,a7,1086 + 129c: 011416b3 sll a3,s0,a7 + 12a0: 00f6e6b3 or a3,a3,a5 + 12a4: 00d036b3 snez a3,a3 + 12a8: 00d767b3 or a5,a4,a3 + 12ac: 00000413 li s0,0 + 12b0: f89ff06f j 1238 <__muldf3+0x614> + FP_MUL_D (R, A, B); + 12b4: 00080437 lui s0,0x80 + FP_PACK_D (r, R); + 12b8: 7ff00693 li a3,2047 + 12bc: 00000813 li a6,0 + 12c0: d29ff06f j fe8 <__muldf3+0x3c4> + 12c4: 00080437 lui s0,0x80 + 12c8: 00000713 li a4,0 + 12cc: fedff06f j 12b8 <__muldf3+0x694> + 12d0: 00000413 li s0,0 + 12d4: 00000713 li a4,0 + 12d8: 7ff00693 li a3,2047 + 12dc: d0dff06f j fe8 <__muldf3+0x3c4> + 12e0: 00000413 li s0,0 + 12e4: 00000713 li a4,0 + 12e8: 00100693 li a3,1 + 12ec: cfdff06f j fe8 <__muldf3+0x3c4> + +000012f0 <__fixunsdfsi>: + FP_DECL_EX; + FP_DECL_D (A); + USItype r; + + FP_INIT_EXCEPTIONS; + FP_UNPACK_RAW_D (A, a); + 12f0: 0145d713 srli a4,a1,0x14 + 12f4: 00100637 lui a2,0x100 +{ + 12f8: 00050693 mv a3,a0 + FP_UNPACK_RAW_D (A, a); + 12fc: fff60793 addi a5,a2,-1 # fffff <_data_lma+0xfe8a7> + 1300: 7ff77713 andi a4,a4,2047 + FP_TO_INT_D (r, A, SI_BITS, 0); + 1304: 3fe00513 li a0,1022 + FP_UNPACK_RAW_D (A, a); + 1308: 00b7f7b3 and a5,a5,a1 + 130c: 01f5d593 srli a1,a1,0x1f + FP_TO_INT_D (r, A, SI_BITS, 0); + 1310: 04e55a63 bge a0,a4,1364 <__fixunsdfsi+0x74> + 1314: 00000513 li a0,0 + 1318: 00059863 bnez a1,1328 <__fixunsdfsi+0x38> + 131c: 41e00593 li a1,1054 + 1320: fff00513 li a0,-1 + 1324: 00e5d463 bge a1,a4,132c <__fixunsdfsi+0x3c> + FP_HANDLE_EXCEPTIONS; + + return r; +} + 1328: 00008067 ret + FP_TO_INT_D (r, A, SI_BITS, 0); + 132c: 00c7e7b3 or a5,a5,a2 + 1330: 43300613 li a2,1075 + 1334: 40e60633 sub a2,a2,a4 + 1338: 01f00593 li a1,31 + 133c: 00c5cc63 blt a1,a2,1354 <__fixunsdfsi+0x64> + 1340: bed70713 addi a4,a4,-1043 # 7ffbed <_data_lma+0x7fe495> + 1344: 00e797b3 sll a5,a5,a4 + 1348: 00c6d533 srl a0,a3,a2 + 134c: 00a7e533 or a0,a5,a0 + 1350: 00008067 ret + 1354: 41300693 li a3,1043 + 1358: 40e68733 sub a4,a3,a4 + 135c: 00e7d533 srl a0,a5,a4 + 1360: 00008067 ret + 1364: 00000513 li a0,0 + 1368: 00008067 ret + +0000136c <__mulsi3>: +/* Our RV64 64-bit routine is equivalent to our RV32 32-bit routine. */ +# define __muldi3 __mulsi3 +#endif + +FUNC_BEGIN (__muldi3) + mv a2, a0 + 136c: 00050613 mv a2,a0 + li a0, 0 + 1370: 00000513 li a0,0 +.L1: + andi a3, a1, 1 + 1374: 0015f693 andi a3,a1,1 + beqz a3, .L2 + 1378: 00068463 beqz a3,1380 <__mulsi3+0x14> + add a0, a0, a2 + 137c: 00c50533 add a0,a0,a2 +.L2: + srli a1, a1, 1 + 1380: 0015d593 srli a1,a1,0x1 + slli a2, a2, 1 + 1384: 00161613 slli a2,a2,0x1 + bnez a1, .L1 + 1388: fe0596e3 bnez a1,1374 <__mulsi3+0x8> + ret + 138c: 00008067 ret + +00001390 <__divsi3>: + li t0, -1 + beq a1, t0, .L20 +#endif + +FUNC_BEGIN (__divdi3) + bltz a0, .L10 + 1390: 06054063 bltz a0,13f0 <__umodsi3+0x10> + bltz a1, .L11 + 1394: 0605c663 bltz a1,1400 <__umodsi3+0x20> + +00001398 <__udivsi3>: + /* Since the quotient is positive, fall into __udivdi3. */ + +FUNC_BEGIN (__udivdi3) + mv a2, a1 + 1398: 00058613 mv a2,a1 + mv a1, a0 + 139c: 00050593 mv a1,a0 + li a0, -1 + 13a0: fff00513 li a0,-1 + beqz a2, .L5 + 13a4: 02060c63 beqz a2,13dc <__udivsi3+0x44> + li a3, 1 + 13a8: 00100693 li a3,1 + bgeu a2, a1, .L2 + 13ac: 00b67a63 bgeu a2,a1,13c0 <__udivsi3+0x28> +.L1: + blez a2, .L2 + 13b0: 00c05863 blez a2,13c0 <__udivsi3+0x28> + slli a2, a2, 1 + 13b4: 00161613 slli a2,a2,0x1 + slli a3, a3, 1 + 13b8: 00169693 slli a3,a3,0x1 + bgtu a1, a2, .L1 + 13bc: feb66ae3 bltu a2,a1,13b0 <__udivsi3+0x18> +.L2: + li a0, 0 + 13c0: 00000513 li a0,0 +.L3: + bltu a1, a2, .L4 + 13c4: 00c5e663 bltu a1,a2,13d0 <__udivsi3+0x38> + sub a1, a1, a2 + 13c8: 40c585b3 sub a1,a1,a2 + or a0, a0, a3 + 13cc: 00d56533 or a0,a0,a3 +.L4: + srli a3, a3, 1 + 13d0: 0016d693 srli a3,a3,0x1 + srli a2, a2, 1 + 13d4: 00165613 srli a2,a2,0x1 + bnez a3, .L3 + 13d8: fe0696e3 bnez a3,13c4 <__udivsi3+0x2c> +.L5: + ret + 13dc: 00008067 ret + +000013e0 <__umodsi3>: +FUNC_END (__udivdi3) + +FUNC_BEGIN (__umoddi3) + /* Call __udivdi3(a0, a1), then return the remainder, which is in a1. */ + move t0, ra + 13e0: 00008293 mv t0,ra + jal __udivdi3 + 13e4: fb5ff0ef jal ra,1398 <__udivsi3> + move a0, a1 + 13e8: 00058513 mv a0,a1 + jr t0 + 13ec: 00028067 jr t0 +FUNC_END (__umoddi3) + + /* Handle negative arguments to __divdi3. */ +.L10: + neg a0, a0 + 13f0: 40a00533 neg a0,a0 + /* Zero is handled as a negative so that the result will not be inverted. */ + bgtz a1, .L12 /* Compute __udivdi3(-a0, a1), then negate the result. */ + 13f4: 00b04863 bgtz a1,1404 <__umodsi3+0x24> + + neg a1, a1 + 13f8: 40b005b3 neg a1,a1 + j __udivdi3 /* Compute __udivdi3(-a0, -a1). */ + 13fc: f9dff06f j 1398 <__udivsi3> +.L11: /* Compute __udivdi3(a0, -a1), then negate the result. */ + neg a1, a1 + 1400: 40b005b3 neg a1,a1 +.L12: + move t0, ra + 1404: 00008293 mv t0,ra + jal __udivdi3 + 1408: f91ff0ef jal ra,1398 <__udivsi3> + neg a0, a0 + 140c: 40a00533 neg a0,a0 + jr t0 + 1410: 00028067 jr t0 + +00001414 <__modsi3>: +FUNC_END (__divdi3) + +FUNC_BEGIN (__moddi3) + move t0, ra + 1414: 00008293 mv t0,ra + bltz a1, .L31 + 1418: 0005ca63 bltz a1,142c <__modsi3+0x18> + bltz a0, .L32 + 141c: 00054c63 bltz a0,1434 <__modsi3+0x20> +.L30: + jal __udivdi3 /* The dividend is not negative. */ + 1420: f79ff0ef jal ra,1398 <__udivsi3> + move a0, a1 + 1424: 00058513 mv a0,a1 + jr t0 + 1428: 00028067 jr t0 +.L31: + neg a1, a1 + 142c: 40b005b3 neg a1,a1 + bgez a0, .L30 + 1430: fe0558e3 bgez a0,1420 <__modsi3+0xc> +.L32: + neg a0, a0 + 1434: 40a00533 neg a0,a0 + jal __udivdi3 /* The dividend is hella negative. */ + 1438: f61ff0ef jal ra,1398 <__udivsi3> + neg a0, a1 + 143c: 40b00533 neg a0,a1 + jr t0 + 1440: 00028067 jr t0 + +00001444 <__clzsi2>: +int +__clzSI2 (UWtype x) +{ + Wtype ret; + + count_leading_zeros (ret, x); + 1444: 000107b7 lui a5,0x10 + 1448: 02f57a63 bgeu a0,a5,147c <__clzsi2+0x38> + 144c: 10053793 sltiu a5,a0,256 + 1450: 0017c793 xori a5,a5,1 + 1454: 00379793 slli a5,a5,0x3 + 1458: 00001737 lui a4,0x1 + 145c: 02000693 li a3,32 + 1460: 40f686b3 sub a3,a3,a5 + 1464: 00f55533 srl a0,a0,a5 + 1468: 65870793 addi a5,a4,1624 # 1658 <__clz_tab> + 146c: 00a787b3 add a5,a5,a0 + 1470: 0007c503 lbu a0,0(a5) # 10000 <_data_lma+0xe8a8> + + return ret; +} + 1474: 40a68533 sub a0,a3,a0 + 1478: 00008067 ret + count_leading_zeros (ret, x); + 147c: 01000737 lui a4,0x1000 + 1480: 01000793 li a5,16 + 1484: fce56ae3 bltu a0,a4,1458 <__clzsi2+0x14> + 1488: 01800793 li a5,24 + 148c: fcdff06f j 1458 <__clzsi2+0x14> diff --git a/contrib/pa/hello.elf b/contrib/pa/hello.elf new file mode 100755 index 0000000..49c1315 Binary files /dev/null and b/contrib/pa/hello.elf differ diff --git a/contrib/pa/minres.png b/contrib/pa/minres.png new file mode 100755 index 0000000..babf0e1 Binary files /dev/null and b/contrib/pa/minres.png differ diff --git a/contrib/tgc_import.cc b/contrib/pa/tgc_import.cc similarity index 100% rename from contrib/tgc_import.cc rename to contrib/pa/tgc_import.cc diff --git a/contrib/tgc_import.tcl b/contrib/pa/tgc_import.tcl similarity index 73% rename from contrib/tgc_import.tcl rename to contrib/pa/tgc_import.tcl index 9726408..4372e3b 100644 --- a/contrib/tgc_import.tcl +++ b/contrib/pa/tgc_import.tcl @@ -6,14 +6,11 @@ proc getScriptDirectory {} { set scriptFolder [file dirname $dispScriptFile] return $scriptFolder } -if { $::env(SNPS_VP_PRODUCT) == "PAULTRA" } { set hardware /HARDWARE/HW/HW -} else { - set hardware /HARDWARE -} set scriptDir [getScriptDirectory] set top_design_name core_complex +set encap_name sysc::tgfs::${top_design_name} set clocks clk_i set resets rst_i set model_prefix "i_" @@ -28,7 +25,8 @@ set model_postfix "" ::pct::set_update_existing_encaps_flag true ::pct::set_dynamic_port_arrays_flag true ::pct::set_import_scml_properties_flag true -::pct::load_modules --set-category modules tgc_import.cc +::pct::set_import_encap_prop_as_extra_prop_flag true +::pct::load_modules --set-category modules ${scriptDir}/tgc_import.cc # Set Port Protocols correctly set block ${top_design_name} @@ -38,13 +36,15 @@ foreach clock ${clocks} { foreach reset ${resets} { ::pct::set_block_port_protocol --set-category SYSTEM_LIBRARY:$block/${reset} SYSTEM_LIBRARY:RESET } -::pct::set_encap_port_array_size SYSTEM_LIBRARY:$block/local_irq_i 16 +#::pct::set_encap_port_array_size SYSTEM_LIBRARY:$block/local_irq_i 16 # Set compile settings and look set block SYSTEM_LIBRARY:${top_design_name} -::pct::set_encap_build_script $block/${top_design_name} $scriptDir/build.tcl +::pct::set_encap_build_script $block/${encap_name} $scriptDir/build.tcl ::pct::set_background_color_rgb $block 255 255 255 255 -::pct::create_instance SYSTEM_LIBRARY:${top_design_name} ${hardware} ${model_prefix}${top_design_name}${model_postfix} ${top_design_name} +::pct::create_instance SYSTEM_LIBRARY:${top_design_name} ${hardware} ${model_prefix}${top_design_name}${model_postfix} ${encap_name} ${encap_name}() +::pct::set_bounds i_${top_design_name} 200 300 100 400 +::pct::set_image i_${top_design_name} "$scriptDir/minres.png" center center false true # export the result as component ::pct::export_system_library ${top_design_name} ${top_design_name}.xml diff --git a/contrib/pa/tgc_import_tb.tcl b/contrib/pa/tgc_import_tb.tcl new file mode 100644 index 0000000..3150eb8 --- /dev/null +++ b/contrib/pa/tgc_import_tb.tcl @@ -0,0 +1,71 @@ +source tgc_import.tcl +set hardware /HARDWARE/HW/HW +set FW_name ${scriptDir}/hello.elf + +puts "instantiate testbench elements" +::paultra::add_hw_instance GenericIPlib:Memory_Generic -inst_name i_Memory_Generic +::pct::set_param_value i_Memory_Generic/MEM:protocol {Protocol Common Parameters} address_width 30 +::pct::set_param_value i_Memory_Generic {Scml Properties} /timing/LT/clock_period_in_ns 1 +::pct::set_param_value i_Memory_Generic {Scml Properties} /timing/read/cmd_accept_cycles 1 +::pct::set_param_value i_Memory_Generic {Scml Properties} /timing/write/cmd_accept_cycles 1 +::pct::set_bounds i_Memory_Generic 1000 300 100 100 + +::paultra::add_hw_instance Bus:Bus -inst_name i_Bus +::BLWizard::generateFramework i_Bus SBLTLM2FT * {} \ + { common_configuration:BackBone:/advanced/num_resources_per_target:1 } +::pct::set_bounds i_Bus 700 300 100 400 +::pct::create_connection C_ibus i_core_complex/ibus i_Bus/i_core_complex_ibus +::pct::set_location_on_owner i_Bus/i_core_complex_ibus 10 +::pct::create_connection C_dbus i_core_complex/dbus i_Bus/i_core_complex_dbus +::pct::set_location_on_owner i_Bus/i_core_complex_dbus 10 +::pct::create_connection C_mem i_Bus/i_Memory_Generic_MEM i_Memory_Generic/MEM + +puts "instantiating clock manager" +set clock "Clk" +::hw::create_hw_instance "" GenericIPlib:ClockGenerator ${clock}_clock +::pct::set_bounds ${clock}_clock 100 100 100 100 +::pct::set_param_value $hardware/${clock}_clock {Constructor Arguments} period 1000 +::pct::set_param_value $hardware/${clock}_clock {Constructor Arguments} period_unit sc_core::SC_PS + +puts "instantiating reset manager" +set reset "Rst" + ::hw::create_hw_instance "" GenericIPlib:ResetGenerator ${reset}_reset + ::pct::set_param_value $hardware/${reset}_reset {Constructor Arguments} start_time 0 + ::pct::set_param_value $hardware/${reset}_reset {Constructor Arguments} start_time_unit sc_core::SC_PS + ::pct::set_param_value $hardware/${reset}_reset {Constructor Arguments} duration 10000 + ::pct::set_param_value $hardware/${reset}_reset {Constructor Arguments} duration_unit sc_core::SC_PS + ::pct::set_param_value $hardware/${reset}_reset {Constructor Arguments} active_level true +::pct::set_bounds ${reset}_reset 300 100 100 100 + +puts "connecting reset/clock" +::pct::create_connection C_clk . Clk_clock/CLK i_core_complex/clk_i +::pct::add_ports_to_connection C_clk i_Bus/Clk +::pct::add_ports_to_connection C_clk i_Memory_Generic/CLK +::pct::create_connection C_rst . Rst_reset/RST i_core_complex/rst_i +::pct::add_ports_to_connection C_rst i_Bus/Rst + +puts "setting parameters for DBT-RISE-TGC/Bus and memory components" +::pct::set_param_value $hardware/i_${top_design_name} {Extra properties} elf_file ${FW_name} +::pct::set_address $hardware/i_${top_design_name}/ibus:i_Memory_Generic/MEM 0x0 +::pct::set_address $hardware/i_${top_design_name}/dbus:i_Memory_Generic/MEM 0x0 +::BLWizard::updateFramework i_Bus {} { common_configuration:BackBone:/advanced/num_resources_per_target:1 } + +::pct::set_main_configuration Default {{#include } {::scc::init_logging(::scc::LogConfig().logLevel(::scc::log::INFO).coloredOutput(false).logAsync(false));} {} {} {}} +::pct::set_main_configuration Debug {{#include } {::scc::init_logging(::scc::LogConfig().logLevel(::scc::log::DEBUG).coloredOutput(false).logAsync(false));} {} {} {}} +::pct::create_simulation_build_config Debug +::pct::set_simulation_build_project_setting Debug "Main Configuration" Default +# add build settings and save design for next steps +#::pct::set_simulation_build_project_setting "Debug" "Linker Flags" "-Wl,-z,muldefs $::env(VERILATOR_ROOT)/include/verilated.cpp $::env(VERILATOR_ROOT)/include/verilated_vcd_sc.cpp $::env(VERILATOR_ROOT)/include/verilated_vcd_c.cpp" +#::pct::set_simulation_build_project_setting "Debug" "Include Paths" $::env(VERILATOR_ROOT)/include/ + +#::simulation::set_simulation_property Simulation [list run_for_duration:200ns results_dir:results/test_0 "TLM Port Trace:true"] +#::simulation::run_simulation Simulation + +#::pct::set_simulation_build_project_setting Debug {Export Type} {STATIC NETLIST} +#::pct::set_simulation_build_project_setting Debug {Encapsulated Netlist} false +#::pct::export_system "export" +#::cd "export" +#::scsh::open-project +#::scsh::build +#::scsh::elab sim +::pct::save_system testbench.xml diff --git a/gen_input/TGC5C.core_desc b/gen_input/TGC5C.core_desc new file mode 100644 index 0000000..f57a6c4 --- /dev/null +++ b/gen_input/TGC5C.core_desc @@ -0,0 +1,13 @@ +import "ISA/RVI.core_desc" +import "ISA/RVM.core_desc" +import "ISA/RVC.core_desc" + +Core TGC5C provides RV32I, Zicsr, Zifencei, RV32M, RV32IC { + architectural_state { + XLEN=32; + // definitions for the architecture wrapper + // XL ZYXWVUTSRQPONMLKJIHGFEDCBA + unsigned int MISA_VAL = 0b01000000000000000001000100000100; + unsigned int MARCHID_VAL = 0x80000003; + } +} diff --git a/gen_input/TGC_C.core_desc b/gen_input/TGC_C.core_desc deleted file mode 100644 index d3a529e..0000000 --- a/gen_input/TGC_C.core_desc +++ /dev/null @@ -1,13 +0,0 @@ -import "CoreDSL-Instruction-Set-Description/RV32I.core_desc" -import "CoreDSL-Instruction-Set-Description/RVM.core_desc" -import "CoreDSL-Instruction-Set-Description/RVC.core_desc" - -Core TGC_C provides RV32I, Zicsr, Zifencei, RV32M, RV32IC { - architectural_state { - XLEN=32; - // definitions for the architecture wrapper - // XL ZYXWVUTSRQPONMLKJIHGFEDCBA - unsigned MISA_VAL = 0b01000000000000000001000100000100; - unsigned MARCHID_VAL = 0x80000003; - } -} diff --git a/gen_input/templates/CORENAME.cpp.gtl b/gen_input/templates/CORENAME.cpp.gtl index 6bb5c4e..7925e90 100644 --- a/gen_input/templates/CORENAME.cpp.gtl +++ b/gen_input/templates/CORENAME.cpp.gtl @@ -33,13 +33,14 @@ def getRegisterSizes(){ def regs = registers.collect{it.size} regs[-1]=64 // correct for NEXT_PC - regs+=[32, 32, 64, 64, 64] // append TRAP_STATE, PENDING_TRAP, ICOUNT, CYCLE, INSTRET + regs+=[32,32, 64, 64, 64, 32, 32] // append TRAP_STATE, PENDING_TRAP, ICOUNT, CYCLE, INSTRET, INSTRUCTION, LAST_BRANCH return regs } %> +// clang-format off +#include "${coreDef.name.toLowerCase()}.h" #include "util/ities.h" #include -#include #include #include #include @@ -51,9 +52,7 @@ constexpr std::array iss::arch::traits iss::arch::traits::reg_bit_widths; constexpr std::array iss::arch::traits::reg_byte_offsets; -${coreDef.name.toLowerCase()}::${coreDef.name.toLowerCase()}() { - reg.icount = 0; -} +${coreDef.name.toLowerCase()}::${coreDef.name.toLowerCase()}() = default; ${coreDef.name.toLowerCase()}::~${coreDef.name.toLowerCase()}() = default; @@ -72,7 +71,7 @@ uint8_t *${coreDef.name.toLowerCase()}::get_regs_base_ptr() { return reinterpret_cast(®); } -${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 +${coreDef.name.toLowerCase()}::phys_addr_t ${coreDef.name.toLowerCase()}::virt2phys(const iss::addr_t &addr) { + return phys_addr_t(addr.access, addr.space, addr.val&traits<${coreDef.name.toLowerCase()}>::addr_mask); } - +// clang-format on diff --git a/gen_input/templates/CORENAME.h.gtl b/gen_input/templates/CORENAME.h.gtl index dbe4c82..d5ba6c4 100644 --- a/gen_input/templates/CORENAME.h.gtl +++ b/gen_input/templates/CORENAME.h.gtl @@ -30,14 +30,12 @@ * *******************************************************************************/ <% -import com.minres.coredsl.util.BigIntegerWithRadix - def nativeTypeSize(int size){ if(size<=8) return 8; else if(size<=16) return 16; else if(size<=32) return 32; else return 64; } def getRegisterSizes(){ def regs = registers.collect{nativeTypeSize(it.size)} - regs+=[32,32, 64, 64, 64] // append TRAP_STATE, PENDING_TRAP, ICOUNT, CYCLE, INSTRET + regs+=[32,32, 64, 64, 64, 32, 32] // append TRAP_STATE, PENDING_TRAP, ICOUNT, CYCLE, INSTRET, INSTRUCTION, LAST_BRANCH return regs } def getRegisterOffsets(){ @@ -57,15 +55,12 @@ def byteSize(int size){ return 128; } def getCString(def val){ - if(val instanceof BigIntegerWithRadix) - return ((BigIntegerWithRadix)val).toCString() - else - return val.toString() + return val.toString()+'ULL' } %> #ifndef _${coreDef.name.toUpperCase()}_H_ #define _${coreDef.name.toUpperCase()}_H_ - +// clang-format off #include #include #include @@ -81,22 +76,17 @@ template <> struct traits<${coreDef.name.toLowerCase()}> { constexpr static char const* const core_type = "${coreDef.name}"; static constexpr std::array reg_names{ - {"${registers.collect{it.name}.join('", "')}"}}; + {"${registers.collect{it.name.toLowerCase()}.join('", "')}"}}; static constexpr std::array reg_aliases{ - {"${registers.collect{it.alias}.join('", "')}"}}; + {"${registers.collect{it.alias.toLowerCase()}.join('", "')}"}}; enum constants {${constants.collect{c -> c.name+"="+getCString(c.value)}.join(', ')}}; constexpr static unsigned FP_REGS_SIZE = ${constants.find {it.name=='FLEN'}?.value?:0}; enum reg_e { - ${registers.collect{it.name}.join(', ')}, NUM_REGS, - TRAP_STATE=NUM_REGS, - PENDING_TRAP, - ICOUNT, - CYCLE, - INSTRET + ${registers.collect{it.name}.join(', ')}, NUM_REGS, TRAP_STATE=NUM_REGS, PENDING_TRAP, ICOUNT, CYCLE, INSTRET, INSTRUCTION, LAST_BRANCH }; using reg_t = uint${addrDataWidth}_t; @@ -121,7 +111,7 @@ template <> struct traits<${coreDef.name.toLowerCase()}> { enum mem_type_e { ${spaces.collect{it.name}.join(', ')} }; - enum class opcode_e : unsigned short {<%instructions.eachWithIndex{instr, index -> %> + enum class opcode_e {<%instructions.eachWithIndex{instr, index -> %> ${instr.instruction.name} = ${index},<%}%> MAX_OPCODE }; @@ -147,14 +137,6 @@ struct ${coreDef.name.toLowerCase()}: public arch_if { inline uint64_t stop_code() { 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(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); - } - virtual phys_addr_t virt2phys(const iss::addr_t& addr); virtual iss::sync_type needed_sync() const { return iss::NO_SYNC; } @@ -169,8 +151,10 @@ struct ${coreDef.name.toLowerCase()}: public arch_if { }}%> uint32_t trap_state = 0, pending_trap = 0; uint64_t icount = 0; + uint64_t cycle = 0; uint64_t instret = 0; - uint32_t last_branch; + uint32_t instruction = 0; + uint32_t last_branch = 0; } reg; #pragma pack(pop) std::array addr_mode; @@ -190,3 +174,4 @@ if(fcsr != null) {%> } } #endif /* _${coreDef.name.toUpperCase()}_H_ */ +// clang-format on diff --git a/gen_input/templates/CORENAME_instr.yaml.gtl b/gen_input/templates/CORENAME_instr.yaml.gtl index 122be5e..d9fdcbf 100644 --- a/gen_input/templates/CORENAME_instr.yaml.gtl +++ b/gen_input/templates/CORENAME_instr.yaml.gtl @@ -8,9 +8,14 @@ instrGroups[groupName]+=it; } instrGroups -}%><%getInstructionGroups().each{name, instrList -> %> -${name}: <% instrList.findAll{!it.instruction.name.startsWith("__")}.each { %> - - ${it.instruction.name}: +}%><%int index = 0; getInstructionGroups().each{name, instrList -> %> +${name}: <% instrList.each { %> + ${it.instruction.name}: + index: ${index++} encoding: ${it.encoding} - mask: ${it.mask}<%}}%> + mask: ${it.mask}<%if(it.attributes.size) {%> + attributes: ${it.attributes}<%}%> + size: ${it.length} + branch: ${it.modifiesPC} + delay: ${it.isConditional?"[1,1]":"1"}<%}}%> diff --git a/gen_input/templates/CORENAME_sysc.cpp.gtl b/gen_input/templates/CORENAME_sysc.cpp.gtl new file mode 100644 index 0000000..6163aa1 --- /dev/null +++ b/gen_input/templates/CORENAME_sysc.cpp.gtl @@ -0,0 +1,131 @@ +/******************************************************************************* + * Copyright (C) 2023 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. + * + *******************************************************************************/ +// clang-format off +#include +#include +#include +#include +#include +#include +#include +<% +def array_count = coreDef.name.toLowerCase()=="tgc5d" || coreDef.name.toLowerCase()=="tgc5e"? 3 : 2; +%> +namespace iss { +namespace interp { +using namespace sysc; +volatile std::array ${coreDef.name.toLowerCase()}_init = { + iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|m_p|interp", [](unsigned gdb_port, void* data) -> iss_factory::base_t { + auto* cc = reinterpret_cast(data); + auto* cpu = new sc_core_adapter>(cc); + return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast(cpu), gdb_port)}}; + }), + iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p|interp", [](unsigned gdb_port, void* data) -> iss_factory::base_t { + auto* cc = reinterpret_cast(data); + auto* cpu = new sc_core_adapter>(cc); + return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast(cpu), gdb_port)}}; + })<%if(coreDef.name.toLowerCase()=="tgc5d" || coreDef.name.toLowerCase()=="tgc5e") {%>, + iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p_clic_pmp|interp", [](unsigned gdb_port, void* data) -> iss_factory::base_t { + auto* cc = reinterpret_cast(data); + auto* cpu = new sc_core_adapter>(cc); + return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast(cpu), gdb_port)}}; + })<%}%> +}; +} +#if defined(WITH_LLVM) +namespace llvm { +using namespace sysc; +volatile std::array ${coreDef.name.toLowerCase()}_init = { + iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|m_p|llvm", [](unsigned gdb_port, void* data) -> iss_factory::base_t { + auto* cc = reinterpret_cast(data); + auto* cpu = new sc_core_adapter>(cc); + return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast(cpu), gdb_port)}}; + }), + iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p|llvm", [](unsigned gdb_port, void* data) -> iss_factory::base_t { + auto* cc = reinterpret_cast(data); + auto* cpu = new sc_core_adapter>(cc); + return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast(cpu), gdb_port)}}; + })<%if(coreDef.name.toLowerCase()=="tgc5d" || coreDef.name.toLowerCase()=="tgc5e") {%>, + iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p_clic_pmp|llvm", [](unsigned gdb_port, void* data) -> iss_factory::base_t { + auto* cc = reinterpret_cast(data); + auto* cpu = new sc_core_adapter>(cc); + return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast(cpu), gdb_port)}}; + })<%}%> +}; +} +#endif +#if defined(WITH_TCC) +namespace tcc { +using namespace sysc; +volatile std::array ${coreDef.name.toLowerCase()}_init = { + iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|m_p|tcc", [](unsigned gdb_port, void* data) -> iss_factory::base_t { + auto* cc = reinterpret_cast(data); + auto* cpu = new sc_core_adapter>(cc); + return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast(cpu), gdb_port)}}; + }), + iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p|tcc", [](unsigned gdb_port, void* data) -> iss_factory::base_t { + auto* cc = reinterpret_cast(data); + auto* cpu = new sc_core_adapter>(cc); + return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast(cpu), gdb_port)}}; + })<%if(coreDef.name.toLowerCase()=="tgc5d" || coreDef.name.toLowerCase()=="tgc5e") {%>, + iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p_clic_pmp|tcc", [](unsigned gdb_port, void* data) -> iss_factory::base_t { + auto* cc = reinterpret_cast(data); + auto* cpu = new sc_core_adapter>(cc); + return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast(cpu), gdb_port)}}; + })<%}%> +}; +} +#endif +#if defined(WITH_ASMJIT) +namespace asmjit { +using namespace sysc; +volatile std::array ${coreDef.name.toLowerCase()}_init = { + iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|m_p|asmjit", [](unsigned gdb_port, void* data) -> iss_factory::base_t { + auto* cc = reinterpret_cast(data); + auto* cpu = new sc_core_adapter>(cc); + return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast(cpu), gdb_port)}}; + }), + iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p|asmjit", [](unsigned gdb_port, void* data) -> iss_factory::base_t { + auto* cc = reinterpret_cast(data); + auto* cpu = new sc_core_adapter>(cc); + return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast(cpu), gdb_port)}}; + })<%if(coreDef.name.toLowerCase()=="tgc5d" || coreDef.name.toLowerCase()=="tgc5e") {%>, + iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p_clic_pmp|asmjit", [](unsigned gdb_port, void* data) -> iss_factory::base_t { + auto* cc = reinterpret_cast(data); + auto* cpu = new sc_core_adapter>(cc); + return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast(cpu), gdb_port)}}; + })<%}%> +}; +} +#endif +} +// clang-format on \ No newline at end of file diff --git a/gen_input/templates/asmjit/CORENAME.cpp.gtl b/gen_input/templates/asmjit/CORENAME.cpp.gtl new file mode 100644 index 0000000..74f54d4 --- /dev/null +++ b/gen_input/templates/asmjit/CORENAME.cpp.gtl @@ -0,0 +1,281 @@ +/******************************************************************************* + * Copyright (C) 2017, 2023 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. + * + *******************************************************************************/ +// clang-format off +#include +#include +#include +#include +#include +#include +#include + +#ifndef FMT_HEADER_ONLY +#define FMT_HEADER_ONLY +#endif +#include + +#include +#include + +namespace iss { +namespace asmjit { + + +namespace ${coreDef.name.toLowerCase()} { +using namespace ::asmjit; +using namespace iss::arch; +using namespace iss::debugger; + +template class vm_impl : public iss::asmjit::vm_base { +public: + using traits = arch::traits; + using super = typename iss::asmjit::vm_base; + 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 mem_type_e = typename super::mem_type_e; + 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) override { + debugger_if::dbg_enabled = true; + if (vm_base::tgt_adapter == nullptr) + vm_base::tgt_adapter = new riscv_target_adapter(srv, this->get_arch()); + return vm_base::tgt_adapter; + } + +protected: + using vm_base::get_reg_ptr; + using this_class = vm_impl; + using compile_func = continuation_e (this_class::*)(virt_addr_t&, code_word_t, jit_holder&); + + continuation_e gen_single_inst_behavior(virt_addr_t&, unsigned int &, jit_holder&) override; + inline const char *name(size_t index){return traits::reg_aliases.at(index);} + + template::type> + inline S sext(U from) { + auto mask = (1ULL< + +private: + /**************************************************************************** + * start opcode definitions + ****************************************************************************/ + struct instruction_descriptor { + size_t length; + uint32_t value; + uint32_t mask; + compile_func op; + }; + struct decoding_tree_node{ + std::vector instrs; + std::vector children; + uint32_t submask = std::numeric_limits::max(); + uint32_t value; + decoding_tree_node(uint32_t value) : value(value){} + }; + + decoding_tree_node* root {nullptr}; + + const std::array instr_descr = {{ + /* entries are: size, valid value, valid mask, function ptr */<%instructions.each{instr -> %> + /* instruction ${instr.instruction.name}, encoding '${instr.encoding}' */ + {${instr.length}, ${instr.encoding}, ${instr.mask}, &this_class::__${generator.functionName(instr.name)}},<%}%> + }}; + + /* instruction definitions */<%instructions.eachWithIndex{instr, idx -> %> + /* instruction ${idx}: ${instr.name} */ + continuation_e __${generator.functionName(instr.name)}(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + <%instr.fields.eachLine{%>${it} + <%}%>if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\\n${instr.name}_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, ${idx}); + pc=pc+ ${instr.length/8}; + + gen_instr_prologue(jh, pc.val); + cc.comment("\\n//behavior:"); + /*generate behavior*/ + <%instr.behavior.eachLine{%>${it} + <%}%> + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, ${idx}); + return returnValue; + } + <%}%> + /**************************************************************************** + * end opcode definitions + ****************************************************************************/ + continuation_e illegal_intruction(virt_addr_t &pc, code_word_t instr, jit_holder& jh ) { + + return BRANCH; + } + //decoding functionality + + void populate_decoding_tree(decoding_tree_node* root){ + //create submask + for(auto instr: root->instrs){ + root->submask &= instr.mask; + } + //put each instr according to submask&encoding into children + for(auto instr: root->instrs){ + bool foundMatch = false; + for(auto child: root->children){ + //use value as identifying trait + if(child->value == (instr.value&root->submask)){ + child->instrs.push_back(instr); + foundMatch = true; + } + } + if(!foundMatch){ + decoding_tree_node* child = new decoding_tree_node(instr.value&root->submask); + child->instrs.push_back(instr); + root->children.push_back(child); + } + } + root->instrs.clear(); + //call populate_decoding_tree for all children + if(root->children.size() >1) + for(auto child: root->children){ + populate_decoding_tree(child); + } + else{ + //sort instrs by value of the mask, this works bc we want to have the least restrictive one last + std::sort(root->children[0]->instrs.begin(), root->children[0]->instrs.end(), [](const instruction_descriptor& instr1, const instruction_descriptor& instr2) { + return instr1.mask > instr2.mask; + }); + } + } + compile_func decode_instr(decoding_tree_node* node, code_word_t word){ + if(!node->children.size()){ + if(node->instrs.size() == 1) return node->instrs[0].op; + for(auto instr : node->instrs){ + if((instr.mask&word) == instr.value) return instr.op; + } + } + else{ + for(auto child : node->children){ + if (child->value == (node->submask&word)){ + return decode_instr(child, word); + } + } + } + return nullptr; + } +}; + +template void debug_fn(CODE_WORD instr) { + volatile CODE_WORD x = instr; + instr = 2 * x; +} + +template vm_impl::vm_impl() { this(new ARCH()); } + +template +vm_impl::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id) +: vm_base(core, core_id, cluster_id) { + root = new decoding_tree_node(std::numeric_limits::max()); + for(auto instr: instr_descr){ + root->instrs.push_back(instr); + } + populate_decoding_tree(root); +} + +template +continuation_e +vm_impl::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, jit_holder& jh) { + enum {TRAP_ID=1<<16}; + code_word_t instr = 0; + phys_addr_t paddr(pc); + auto *const data = (uint8_t *)&instr; + if(this->core.has_mmu()) + paddr = this->core.virt2phys(pc); + auto res = this->core.read(paddr, 4, data); + if (res != iss::Ok) + throw trap_access(TRAP_ID, pc.val); + if (instr == 0x0000006f || (instr&0xffff)==0xa001) + throw simulation_stopped(0); // 'J 0' or 'C.J 0' + ++inst_cnt; + auto f = decode_instr(root, instr); + if (f == nullptr) + f = &this_class::illegal_intruction; + return (this->*f)(pc, instr, jh); +} + + + +} // namespace ${coreDef.name.toLowerCase()} + +template <> +std::unique_ptr create(arch::${coreDef.name.toLowerCase()} *core, unsigned short port, bool dump) { + auto ret = new ${coreDef.name.toLowerCase()}::vm_impl(*core, dump); + if (port != 0) debugger::server::run_server(ret, port); + return std::unique_ptr(ret); +} +} // namespace asmjit +} // namespace iss + +#include +#include +#include +namespace iss { +namespace { +volatile std::array dummy = { + core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|m_p|asmjit", [](unsigned port, void*) -> std::tuple{ + auto* cpu = new iss::arch::riscv_hart_m_p(); + auto* vm = new asmjit::${coreDef.name.toLowerCase()}::vm_impl(*cpu, false); + if (port != 0) debugger::server::run_server(vm, port); + return {cpu_ptr{cpu}, vm_ptr{vm}}; + }), + core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p|asmjit", [](unsigned port, void*) -> std::tuple{ + auto* cpu = new iss::arch::riscv_hart_mu_p(); + auto* vm = new asmjit::${coreDef.name.toLowerCase()}::vm_impl(*cpu, false); + if (port != 0) debugger::server::run_server(vm, port); + return {cpu_ptr{cpu}, vm_ptr{vm}}; + }) +}; +} +} +// clang-format on \ No newline at end of file diff --git a/gen_input/templates/interp/CORENAME.cpp.gtl b/gen_input/templates/interp/CORENAME.cpp.gtl index 98817ce..c2eb071 100644 --- a/gen_input/templates/interp/CORENAME.cpp.gtl +++ b/gen_input/templates/interp/CORENAME.cpp.gtl @@ -30,23 +30,23 @@ * *******************************************************************************/ <% -import com.minres.coredsl.util.BigIntegerWithRadix - def nativeTypeSize(int size){ if(size<=8) return 8; else if(size<=16) return 16; else if(size<=32) return 32; else return 64; } %> -#include "../fp_functions.h" +// clang-format off #include -#include #include #include #include #include +#include #include -#include #include #include +#include +#include +#include #ifndef FMT_HEADER_ONLY #define FMT_HEADER_ONLY @@ -63,6 +63,10 @@ using namespace iss::arch; using namespace iss::debugger; using namespace std::placeholders; +struct memory_access_exception : public std::exception{ + memory_access_exception(){} +}; + template class vm_impl : public iss::interp::vm_base { public: using traits = arch::traits; @@ -73,6 +77,7 @@ public: using addr_t = typename super::addr_t; using reg_t = typename traits::reg_t; using mem_type_e = typename traits::mem_type_e; + using opcode_e = typename traits::opcode_e; vm_impl(); @@ -92,37 +97,16 @@ protected: using compile_ret_t = virt_addr_t; using compile_func = compile_ret_t (this_class::*)(virt_addr_t &pc, code_word_t instr); - inline const char *name(size_t index){return traits::reg_aliases.at(index);} + inline const char *name(size_t index){return index::opcode_e decode_inst_id(code_word_t instr); virt_addr_t execute_inst(finish_cond_e cond, virt_addr_t start, uint64_t icount_limit) override; // 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(static_cast(EXTR_MASK32)), - LUT_SIZE_C = 1 << util::bit_count(static_cast(EXTR_MASK16)) - }; - - std::array lut; - - std::array lut_00, lut_01, lut_10; - std::array lut_11; - - struct instruction_pattern { - uint32_t value; - uint32_t mask; - typename arch::traits::opcode_e id; - }; - - std::array, 4> qlut; inline void raise(uint16_t trap_id, uint16_t cause){ auto trap_val = 0x80ULL << 24 | (cause << 16) | trap_id; - this->template get_reg(traits::TRAP_STATE) = trap_val; - this->template get_reg(traits::NEXT_PC) = std::numeric_limits::max(); + this->core.reg.trap_state = trap_val; + this->template get_reg(traits::NEXT_PC) = std::numeric_limits::max(); } inline void leave(unsigned lvl){ @@ -137,44 +121,6 @@ protected: using coro_t = boost::coroutines2::coroutine::pull_type; std::vector spawn_blocks; - template - T& pc_assign(T& val){super::ex_info.branch_taken=true; return val;} - inline uint8_t readSpace1(typename super::mem_type_e space, uint64_t addr){ - auto ret = super::template read_mem(space, addr); - if(this->template get_reg(traits::TRAP_STATE)) throw 0; - return ret; - } - inline uint16_t readSpace2(typename super::mem_type_e space, uint64_t addr){ - auto ret = super::template read_mem(space, addr); - if(this->template get_reg(traits::TRAP_STATE)) throw 0; - return ret; - } - inline uint32_t readSpace4(typename super::mem_type_e space, uint64_t addr){ - auto ret = super::template read_mem(space, addr); - if(this->template get_reg(traits::TRAP_STATE)) throw 0; - return ret; - } - inline uint64_t readSpace8(typename super::mem_type_e space, uint64_t addr){ - auto ret = super::template read_mem(space, addr); - if(this->template get_reg(traits::TRAP_STATE)) throw 0; - return ret; - } - inline void writeSpace1(typename super::mem_type_e space, uint64_t addr, uint8_t data){ - super::write_mem(space, addr, data); - if(this->template get_reg(traits::TRAP_STATE)) throw 0; - } - inline void writeSpace2(typename super::mem_type_e space, uint64_t addr, uint16_t data){ - super::write_mem(space, addr, data); - if(this->template get_reg(traits::TRAP_STATE)) throw 0; - } - inline void writeSpace4(typename super::mem_type_e space, uint64_t addr, uint32_t data){ - super::write_mem(space, addr, data); - if(this->template get_reg(traits::TRAP_STATE)) throw 0; - } - inline void writeSpace8(typename super::mem_type_e space, uint64_t addr, uint64_t data){ - super::write_mem(space, addr, data); - if(this->template get_reg(traits::TRAP_STATE)) throw 0; - } template::type> inline S sext(U from) { auto mask = (1ULL< ${it}<%}%> <%}%> + private: /**************************************************************************** * start opcode definitions ****************************************************************************/ - struct InstructionDesriptor { + struct instruction_descriptor { size_t length; uint32_t value; uint32_t mask; typename arch::traits::opcode_e op; }; + struct decoding_tree_node{ + std::vector instrs; + std::vector children; + uint32_t submask = std::numeric_limits::max(); + uint32_t value; + decoding_tree_node(uint32_t value) : value(value){} + }; - const std::array instr_descr = {{ + decoding_tree_node* root {nullptr}; + const std::array instr_descr = {{ /* entries are: size, valid value, valid mask, function ptr */<%instructions.each{instr -> %> {${instr.length}, ${instr.encoding}, ${instr.mask}, arch::traits::opcode_e::${instr.instruction.name}},<%}%> }}; - //static constexpr typename traits::addr_t upper_bits = ~traits::PGMASK; iss::status fetch_ins(virt_addr_t pc, uint8_t * data){ - auto phys_pc = this->core.v2p(pc); - //if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary - // if (this->core.read(phys_pc, 2, data) != iss::Ok) return iss::Err; - // if ((data[0] & 0x3) == 0x3) // this is a 32bit instruction - // if (this->core.read(this->core.v2p(pc + 2), 2, data + 2) != iss::Ok) return iss::Err; - //} else { - if (this->core.read(phys_pc, 4, data) != iss::Ok) return iss::Err; - //} + if(this->core.has_mmu()) { + auto phys_pc = this->core.virt2phys(pc); +// if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary +// if (this->core.read(phys_pc, 2, data) != iss::Ok) return iss::Err; +// if ((data[0] & 0x3) == 0x3) // this is a 32bit instruction +// if (this->core.read(this->core.v2p(pc + 2), 2, data + 2) != iss::Ok) +// return iss::Err; +// } else { + if (this->core.read(phys_pc, 4, data) != iss::Ok) + return iss::Err; +// } + } else { + if (this->core.read(phys_addr_t(pc.access, pc.space, pc.val), 4, data) != iss::Ok) + return iss::Err; + + } return iss::Ok; } + + void populate_decoding_tree(decoding_tree_node* root){ + //create submask + for(auto instr: root->instrs){ + root->submask &= instr.mask; + } + //put each instr according to submask&encoding into children + for(auto instr: root->instrs){ + bool foundMatch = false; + for(auto child: root->children){ + //use value as identifying trait + if(child->value == (instr.value&root->submask)){ + child->instrs.push_back(instr); + foundMatch = true; + } + } + if(!foundMatch){ + decoding_tree_node* child = new decoding_tree_node(instr.value&root->submask); + child->instrs.push_back(instr); + root->children.push_back(child); + } + } + root->instrs.clear(); + //call populate_decoding_tree for all children + if(root->children.size() >1) + for(auto child: root->children){ + populate_decoding_tree(child); + } + else{ + //sort instrs by value of the mask, this works bc we want to have the least restrictive one last + std::sort(root->children[0]->instrs.begin(), root->children[0]->instrs.end(), [](const instruction_descriptor& instr1, const instruction_descriptor& instr2) { + return instr1.mask > instr2.mask; + }); + } + } + typename arch::traits::opcode_e decode_instr(decoding_tree_node* node, code_word_t word){ + if(!node->children.size()){ + if(node->instrs.size() == 1) return node->instrs[0].op; + for(auto instr : node->instrs){ + if((instr.mask&word) == instr.value) return instr.op; + } + } + else{ + for(auto child : node->children){ + if (child->value == (node->submask&word)){ + return decode_instr(child, word); + } + } + } + return arch::traits::opcode_e::MAX_OPCODE; + } }; template void debug_fn(CODE_WORD insn) { @@ -247,16 +261,11 @@ constexpr size_t bit_count(uint32_t u) { template vm_impl::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id) : vm_base(core, core_id, cluster_id) { - unsigned id=0; - for (auto instr : instr_descr) { - auto quadrant = instr.value & 0x3; - qlut[quadrant].push_back(instruction_pattern{instr.value, instr.mask, instr.op}); - } - for(auto& lut: qlut){ - std::sort(std::begin(lut), std::end(lut), [](instruction_pattern const& a, instruction_pattern const& b){ - return bit_count(a.mask) > bit_count(b.mask); - }); + root = new decoding_tree_node(std::numeric_limits::max()); + for(auto instr:instr_descr){ + root->instrs.push_back(instr); } + populate_decoding_tree(root); } inline bool is_count_limit_enabled(finish_cond_e cond){ @@ -267,83 +276,77 @@ inline bool is_jump_to_self_enabled(finish_cond_e cond){ return (cond & finish_cond_e::JUMP_TO_SELF) == finish_cond_e::JUMP_TO_SELF; } -template -typename arch::traits::opcode_e vm_impl::decode_inst_id(code_word_t instr){ - for(auto& e: qlut[instr&0x3]){ - if(!((instr&e.mask) ^ e.value )) return e.id; - } - return arch::traits::opcode_e::MAX_OPCODE; -} - template typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e cond, virt_addr_t start, uint64_t icount_limit){ - // we fetch at max 4 byte, alignment is 2 - code_word_t instr = 0; - auto *const data = (uint8_t *)&instr; auto pc=start; - - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - auto* icount = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]); - auto* instret = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + auto& trap_state = this->core.reg.trap_state; + auto& icount = this->core.reg.icount; + auto& cycle = this->core.reg.cycle; + auto& instret = this->core.reg.instret; + auto& instr = this->core.reg.instruction; + // we fetch at max 4 byte, alignment is 2 + auto *const data = reinterpret_cast(&instr); while(!this->core.should_stop() && - !(is_count_limit_enabled(cond) && this->core.get_icount() >= icount_limit)){ + !(is_count_limit_enabled(cond) && icount >= icount_limit)){ if(fetch_ins(pc, data)!=iss::Ok){ this->do_sync(POST_SYNC, std::numeric_limits::max()); pc.val = super::core.enter_trap(std::numeric_limits::max(), pc.val, 0); } else { if (is_jump_to_self_enabled(cond) && (instr == 0x0000006f || (instr&0xffff)==0xa001)) throw simulation_stopped(0); // 'J 0' or 'C.J 0' - auto inst_id = decode_inst_id(instr); + auto inst_id = decode_instr(root, instr); // pre execution stuff + this->core.reg.last_branch = 0; if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, static_cast(inst_id)); - switch(inst_id){<%instructions.eachWithIndex{instr, idx -> %> - case arch::traits::opcode_e::${instr.name}: { - <%instr.fields.eachLine{%>${it} - <%}%>if(this->disass_enabled){ - /* generate console output when executing the command */ - <%instr.disass.eachLine{%>${it} - <%}%> - } - // used registers<%instr.usedVariables.each{ k,v-> - if(v.isArray) {%> - auto* ${k} = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::${k}0]);<% }else{ %> - auto* ${k} = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::${k}]); - <%}}%>// calculate next pc value - *NEXT_PC = *PC + ${instr.length/8}; - // execute instruction - try { - <%instr.behavior.eachLine{%>${it} - <%}%>} catch(...){} - } - break;<%}%> - default: { - *NEXT_PC = *PC + ((instr & 3) == 3 ? 4 : 2); - raise(0, 2); - } - } + try{ + switch(inst_id){<%instructions.eachWithIndex{instr, idx -> %> + case arch::traits::opcode_e::${instr.name}: { + <%instr.fields.eachLine{%>${it} + <%}%>if(this->disass_enabled){ + /* generate console output when executing the command */<%instr.disass.eachLine{%> + ${it}<%}%> + } + // used registers<%instr.usedVariables.each{ k,v-> + if(v.isArray) {%> + auto* ${k} = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::${k}0]);<% }else{ %> + auto* ${k} = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::${k}]); + <%}}%>// calculate next pc value + *NEXT_PC = *PC + ${instr.length/8}; + // execute instruction<%instr.behavior.eachLine{%> + ${it}<%}%> + break; + }// @suppress("No break at end of case")<%}%> + default: { + *NEXT_PC = *PC + ((instr & 3) == 3 ? 4 : 2); + raise(0, 2); + } + } + }catch(memory_access_exception& e){} // post execution stuff process_spawn_blocks(); if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, static_cast(inst_id)); + // if(!this->core.reg.trap_state) // update trap state if there is a pending interrupt + // this->core.reg.trap_state = this->core.reg.pending_trap; // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); + if(trap_state!=0){ + super::core.enter_trap(trap_state, pc.val, instr); } else { - (*icount)++; - (*instret)++; + icount++; + instret++; } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; + cycle++; pc.val=*NEXT_PC; this->core.reg.PC = this->core.reg.NEXT_PC; - this->core.reg.trap_state = this->core.reg.pending_trap; + this->core.reg.trap_state = this->core.reg.pending_trap; } } return pc; } -} +} // namespace ${coreDef.name.toLowerCase()} template <> std::unique_ptr create(arch::${coreDef.name.toLowerCase()} *core, unsigned short port, bool dump) { @@ -353,3 +356,26 @@ std::unique_ptr create(arch::${coreD } } // namespace interp } // namespace iss + +#include +#include +#include +namespace iss { +namespace { +volatile std::array dummy = { + core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|m_p|interp", [](unsigned port, void*) -> std::tuple{ + auto* cpu = new iss::arch::riscv_hart_m_p(); + auto vm = new interp::${coreDef.name.toLowerCase()}::vm_impl(*cpu, false); + if (port != 0) debugger::server::run_server(vm, port); + return {cpu_ptr{cpu}, vm_ptr{vm}}; + }), + core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p|interp", [](unsigned port, void*) -> std::tuple{ + auto* cpu = new iss::arch::riscv_hart_mu_p(); + auto vm = new interp::${coreDef.name.toLowerCase()}::vm_impl(*cpu, false); + if (port != 0) debugger::server::run_server(vm, port); + return {cpu_ptr{cpu}, vm_ptr{vm}}; + }) +}; +} +} +// clang-format on \ No newline at end of file diff --git a/gen_input/templates/llvm/vm-vm_CORENAME.cpp.gtl b/gen_input/templates/llvm/CORENAME.cpp.gtl similarity index 54% rename from gen_input/templates/llvm/vm-vm_CORENAME.cpp.gtl rename to gen_input/templates/llvm/CORENAME.cpp.gtl index 881cb30..5945e35 100644 --- a/gen_input/templates/llvm/vm-vm_CORENAME.cpp.gtl +++ b/gen_input/templates/llvm/CORENAME.cpp.gtl @@ -29,9 +29,8 @@ * POSSIBILITY OF SUCH DAMAGE. * *******************************************************************************/ - +// clang-format off #include -#include #include #include #include @@ -59,6 +58,7 @@ using namespace iss::debugger; template class vm_impl : public iss::llvm::vm_base { public: + using traits = arch::traits; using super = typename iss::llvm::vm_base; using virt_addr_t = typename super::virt_addr_t; using phys_addr_t = typename super::phys_addr_t; @@ -81,7 +81,7 @@ public: protected: using vm_base::get_reg_ptr; - inline const char *name(size_t index){return traits::reg_aliases.at(index);} + inline const char *name(size_t index){return traits::reg_aliases.at(index);} template inline ConstantInt *size(T type) { return ConstantInt::get(getContext(), APInt(32, type->getType()->getScalarSizeInBits())); @@ -89,7 +89,7 @@ protected: void setup_module(Module* m) override { super::setup_module(m); - iss::llvm::fp_impl::add_fp_functions_2_module(m, traits::FP_REGS_SIZE, traits::XLEN); + iss::llvm::fp_impl::add_fp_functions_2_module(m, traits::FP_REGS_SIZE, traits::XLEN); } inline Value *gen_choose(Value *cond, Value *trueVal, Value *falseVal, unsigned size) { @@ -111,92 +111,74 @@ protected: void gen_trap_check(BasicBlock *bb); inline Value *gen_reg_load(unsigned i, unsigned level = 0) { - return this->builder.CreateLoad(get_reg_ptr(i), false); + return this->builder.CreateLoad(this->get_typeptr(i), get_reg_ptr(i), false); } inline void gen_set_pc(virt_addr_t pc, unsigned reg_num) { - Value *next_pc_v = this->builder.CreateSExtOrTrunc(this->gen_const(traits::XLEN, pc.val), - this->get_type(traits::XLEN)); + Value *next_pc_v = this->builder.CreateSExtOrTrunc(this->gen_const(traits::XLEN, pc.val), + this->get_type(traits::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; using compile_func = std::tuple (this_class::*)(virt_addr_t &pc, code_word_t instr, BasicBlock *bb); - std::array lut; - - std::array lut_00, lut_01, lut_10; - std::array lut_11; - - std::array qlut; - - std::array 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; - } + template::type> + inline S sext(U from) { + auto mask = (1ULL< instrs; + std::vector children; + uint32_t submask = std::numeric_limits::max(); + uint32_t value; + decoding_tree_node(uint32_t value) : value(value){} + }; - const std::array instr_descr = {{ + decoding_tree_node* root {nullptr}; + + const std::array instr_descr = {{ /* entries are: size, valid value, valid mask, function ptr */<%instructions.each{instr -> %> - /* instruction ${instr.instruction.name} */ - {${instr.length}, ${instr.value}, ${instr.mask}, &this_class::__${generator.functionName(instr.name)}},<%}%> + /* instruction ${instr.instruction.name}, encoding '${instr.encoding}' */ + {${instr.length}, ${instr.encoding}, ${instr.mask}, &this_class::__${generator.functionName(instr.name)}},<%}%> }}; /* instruction definitions */<%instructions.eachWithIndex{instr, idx -> %> /* instruction ${idx}: ${instr.name} */ - std::tuple __${generator.functionName(instr.name)}(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){<%instr.code.eachLine{%> - ${it}<%}%> + std::tuple __${generator.functionName(instr.name)}(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("${instr.name}_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,${idx}); + uint64_t PC = pc.val; + <%instr.fields.eachLine{%>${it} + <%}%>if(this->disass_enabled){ + /* generate console output when executing the command */<%instr.disass.eachLine{%> + ${it}<%}%> + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ ${instr.length/8}; + this->gen_set_pc(pc, traits::NEXT_PC); + <%instr.behavior.eachLine{%>${it} + <%}%> + this->gen_trap_check(bb); + this->gen_sync(POST_SYNC, ${idx}); + this->builder.CreateBr(bb); + return returnValue; } <%}%> /**************************************************************************** @@ -204,23 +186,75 @@ private: ****************************************************************************/ std::tuple 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::NEXT_PC), true), - get_reg_ptr(traits::PC), true); + this->builder.CreateStore(this->builder.CreateLoad(this->get_typeptr(traits::NEXT_PC), get_reg_ptr(traits::NEXT_PC), true), + get_reg_ptr(traits::PC), true); this->builder.CreateStore( - this->builder.CreateAdd(this->builder.CreateLoad(get_reg_ptr(traits::ICOUNT), true), + this->builder.CreateAdd(this->builder.CreateLoad(this->get_typeptr(traits::ICOUNT), get_reg_ptr(traits::ICOUNT), true), this->gen_const(64U, 1)), - get_reg_ptr(traits::ICOUNT), true); + get_reg_ptr(traits::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(BRANCH, nullptr); + } + //decoding functionality + + void populate_decoding_tree(decoding_tree_node* root){ + //create submask + for(auto instr: root->instrs){ + root->submask &= instr.mask; + } + //put each instr according to submask&encoding into children + for(auto instr: root->instrs){ + bool foundMatch = false; + for(auto child: root->children){ + //use value as identifying trait + if(child->value == (instr.value&root->submask)){ + child->instrs.push_back(instr); + foundMatch = true; + } + } + if(!foundMatch){ + decoding_tree_node* child = new decoding_tree_node(instr.value&root->submask); + child->instrs.push_back(instr); + root->children.push_back(child); + } + } + root->instrs.clear(); + //call populate_decoding_tree for all children + if(root->children.size() >1) + for(auto child: root->children){ + populate_decoding_tree(child); + } + else{ + //sort instrs by value of the mask, this works bc we want to have the least restrictive one last + std::sort(root->children[0]->instrs.begin(), root->children[0]->instrs.end(), [](const instruction_descriptor& instr1, const instruction_descriptor& instr2) { + return instr1.mask > instr2.mask; + }); + } + } + compile_func decode_instr(decoding_tree_node* node, code_word_t word){ + if(!node->children.size()){ + if(node->instrs.size() == 1) return node->instrs[0].op; + for(auto instr : node->instrs){ + if((instr.mask&word) == instr.value) return instr.op; + } + } + else{ + for(auto child : node->children){ + if (child->value == (node->submask&word)){ + return decode_instr(child, word); + } + } + } + return nullptr; } }; -template void debug_fn(CODE_WORD insn) { - volatile CODE_WORD x = insn; - insn = 2 * x; +template void debug_fn(CODE_WORD instr) { + volatile CODE_WORD x = instr; + instr = 2 * x; } template vm_impl::vm_impl() { this(new ARCH()); } @@ -228,14 +262,11 @@ template vm_impl::vm_impl() { this(new ARCH()); } template vm_impl::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id) : vm_base(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); + root = new decoding_tree_node(std::numeric_limits::max()); + for(auto instr:instr_descr){ + root->instrs.push_back(instr); } + populate_decoding_tree(root); } template @@ -243,49 +274,50 @@ std::tuple vm_impl::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::addr_t upper_bits = ~traits::PGMASK; + code_word_t instr = 0; + // const typename traits::addr_t upper_bits = ~traits::PGMASK; phys_addr_t paddr(pc); - 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); - } - } else { + auto *const data = (uint8_t *)&instr; + if(this->core.has_mmu()) + paddr = this->core.virt2phys(pc); + //TODO: re-add page handling +// 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 ((instr & 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(TRAP_ID, pc.val); - } - if (insn == 0x0000006f || (insn&0xffff)==0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0' +// } + if (instr == 0x0000006f || (instr&0xffff)==0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0' // curr pc on stack ++inst_cnt; - auto lut_val = extract_fields(insn); - auto f = qlut[insn & 0x3][lut_val]; + auto f = decode_instr(root, instr); if (f == nullptr) { f = &this_class::illegal_intruction; } - return (this->*f)(pc, insn, this_block); + return (this->*f)(pc, instr, this_block); } template void vm_impl::gen_leave_behavior(BasicBlock *leave_blk) { this->builder.SetInsertPoint(leave_blk); - this->builder.CreateRet(this->builder.CreateLoad(get_reg_ptr(arch::traits::NEXT_PC), false)); + this->builder.CreateRet(this->builder.CreateLoad(this->get_typeptr(traits::NEXT_PC),get_reg_ptr(traits::NEXT_PC), false)); } template void vm_impl::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::TRAP_STATE), true); - this->builder.CreateStore(this->gen_const(32U, std::numeric_limits::max()), get_reg_ptr(traits::LAST_BRANCH), false); + this->builder.CreateStore(TRAP_val, get_reg_ptr(traits::TRAP_STATE), true); + this->builder.CreateStore(this->gen_const(32U, std::numeric_limits::max()), get_reg_ptr(traits::LAST_BRANCH), false); } template void vm_impl::gen_leave_trap(unsigned lvl) { std::vector 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::CSR, (lvl << 8) + 0x41, traits::XLEN / 8); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - this->builder.CreateStore(this->gen_const(32U, std::numeric_limits::max()), get_reg_ptr(traits::LAST_BRANCH), false); + auto *PC_val = this->gen_read_mem(traits::CSR, (lvl << 8) + 0x41, traits::XLEN / 8); + this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); + this->builder.CreateStore(this->gen_const(32U, std::numeric_limits::max()), get_reg_ptr(traits::LAST_BRANCH), false); } template void vm_impl::gen_wait(unsigned type) { @@ -295,22 +327,25 @@ template void vm_impl::gen_wait(unsigned type) { template void vm_impl::gen_trap_behavior(BasicBlock *trap_blk) { this->builder.SetInsertPoint(trap_blk); - auto *trap_state_val = this->builder.CreateLoad(get_reg_ptr(traits::TRAP_STATE), true); + this->gen_sync(POST_SYNC, -1); //TODO get right InstrId + auto *trap_state_val = this->builder.CreateLoad(this->get_typeptr(traits::TRAP_STATE), get_reg_ptr(traits::TRAP_STATE), true); this->builder.CreateStore(this->gen_const(32U, std::numeric_limits::max()), - get_reg_ptr(traits::LAST_BRANCH), false); + get_reg_ptr(traits::LAST_BRANCH), false); std::vector args{this->core_ptr, this->adj_to64(trap_state_val), - this->adj_to64(this->builder.CreateLoad(get_reg_ptr(traits::PC), false))}; + this->adj_to64(this->builder.CreateLoad(this->get_typeptr(traits::PC), get_reg_ptr(traits::PC), false))}; this->builder.CreateCall(this->mod->getFunction("enter_trap"), args); - auto *trap_addr_val = this->builder.CreateLoad(get_reg_ptr(traits::NEXT_PC), false); + auto *trap_addr_val = this->builder.CreateLoad(this->get_typeptr(traits::NEXT_PC), get_reg_ptr(traits::NEXT_PC), false); this->builder.CreateRet(trap_addr_val); } template inline void vm_impl::gen_trap_check(BasicBlock *bb) { - auto *v = this->builder.CreateLoad(get_reg_ptr(arch::traits::TRAP_STATE), true); + auto* target_bb = BasicBlock::Create(this->mod->getContext(), "", this->func, bb); + auto *v = this->builder.CreateLoad(this->get_typeptr(traits::TRAP_STATE), get_reg_ptr(traits::TRAP_STATE), true); this->gen_cond_branch(this->builder.CreateICmp( ICmpInst::ICMP_EQ, v, ConstantInt::get(getContext(), APInt(v->getType()->getIntegerBitWidth(), 0))), - bb, this->trap_blk, 1); + target_bb, this->trap_blk, 1); + this->builder.SetInsertPoint(target_bb); } } // namespace ${coreDef.name.toLowerCase()} @@ -323,3 +358,26 @@ std::unique_ptr create(arch::${coreD } } // namespace llvm } // namespace iss + +#include +#include +#include +namespace iss { +namespace { +volatile std::array dummy = { + core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|m_p|llvm", [](unsigned port, void*) -> std::tuple{ + auto* cpu = new iss::arch::riscv_hart_m_p(); + auto* vm = new llvm::${coreDef.name.toLowerCase()}::vm_impl(*cpu, false); + if (port != 0) debugger::server::run_server(vm, port); + return {cpu_ptr{cpu}, vm_ptr{vm}}; + }), + core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p|llvm", [](unsigned port, void*) -> std::tuple{ + auto* cpu = new iss::arch::riscv_hart_mu_p(); + auto* vm = new llvm::${coreDef.name.toLowerCase()}::vm_impl(*cpu, false); + if (port != 0) debugger::server::run_server(vm, port); + return {cpu_ptr{cpu}, vm_ptr{vm}}; + }) +}; +} +} +// clang-format on \ No newline at end of file diff --git a/gen_input/templates/llvm/CORENAME_cyles.txt.gtl b/gen_input/templates/llvm/CORENAME_cyles.txt.gtl deleted file mode 100644 index 3a1ad8e..0000000 --- a/gen_input/templates/llvm/CORENAME_cyles.txt.gtl +++ /dev/null @@ -1,9 +0,0 @@ -{ - "${coreDef.name}" : [<%instructions.eachWithIndex{instr,index -> %>${index==0?"":","} - { - "name" : "${instr.name}", - "size" : ${instr.length}, - "delay" : ${generator.hasAttribute(instr.instruction, com.minres.coredsl.coreDsl.InstrAttribute.COND)?[1,1]:1} - }<%}%> - ] -} \ No newline at end of file diff --git a/gen_input/templates/llvm/incl-CORENAME.h.gtl b/gen_input/templates/llvm/incl-CORENAME.h.gtl deleted file mode 100644 index 0a5b99f..0000000 --- a/gen_input/templates/llvm/incl-CORENAME.h.gtl +++ /dev/null @@ -1,223 +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. - * - *******************************************************************************/ - -<% -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 -#include -#include -#include - -namespace iss { -namespace arch { - -struct ${coreDef.name.toLowerCase()}; - -template <> struct traits<${coreDef.name.toLowerCase()}> { - - constexpr static char const* const core_type = "${coreDef.name}"; - - static constexpr std::array reg_names{ - {"${getRegisterNames().join("\", \"")}"}}; - - static constexpr std::array 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}; - - enum reg_e {<% - allRegs.each { reg -> - if( reg instanceof RegisterFile) { - (reg.range.right..reg.range.left).each{%> - ${reg.name}${it},<% - } - } else if(reg instanceof Register){ %> - ${reg.name},<% - } - }%> - NUM_REGS, - NEXT_${pc.name}=NUM_REGS, - TRAP_STATE, - PENDING_TRAP, - MACHINE_STATE, - LAST_BRANCH, - ICOUNT<% - allRegs.each { reg -> - if(reg instanceof RegisterAlias){ def aliasname=getOriginalName(reg)%>, - ${reg.name} = ${aliasname}<% - } - }%> - }; - - using reg_t = uint${regDataWidth}_t; - - using addr_t = uint${addrDataWidth}_t; - - using code_word_t = uint${addrDataWidth}_t; //TODO: check removal - - using virt_addr_t = iss::typed_addr_t; - - using phys_addr_t = iss::typed_addr_t; - - static constexpr std::array reg_bit_widths{ - {${regSizes.join(",")}}}; - - static constexpr std::array 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 mem_type_e { ${allSpaces.collect{s -> s.name}.join(', ')} }; -}; - -struct ${coreDef.name.toLowerCase()}: public arch_if { - - using virt_addr_t = typename traits<${coreDef.name.toLowerCase()}>::virt_addr_t; - using phys_addr_t = typename traits<${coreDef.name.toLowerCase()}>::phys_addr_t; - using reg_t = typename traits<${coreDef.name.toLowerCase()}>::reg_t; - using addr_t = typename traits<${coreDef.name.toLowerCase()}>::addr_t; - - ${coreDef.name.toLowerCase()}(); - ~${coreDef.name.toLowerCase()}(); - - void reset(uint64_t address=0) override; - - uint8_t* get_regs_base_ptr() override; - /// deprecated - void get_reg(short idx, std::vector& value) override {} - void set_reg(short idx, const std::vector& 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 uint64_t stop_code() { 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(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); - } - - 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 ${coreDef.name}_regs {<% - allRegs.each { reg -> - if( reg instanceof RegisterFile) { - (reg.range.right..reg.range.left).each{%> - uint${generator.getSize(reg)}_t ${reg.name}${it} = 0;<% - } - } else if(reg instanceof Register){ %> - uint${generator.getSize(reg)}_t ${reg.name} = 0;<% - } - }%> - uint${generator.getSize(pc)}_t NEXT_${pc.name} = 0; - uint32_t trap_state = 0, pending_trap = 0, machine_state = 0, last_branch = 0; - uint64_t icount = 0; - } reg; - - std::array addr_mode; - - uint64_t interrupt_sim=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){} -<%}%> -}; - -} -} -#endif /* _${coreDef.name.toUpperCase()}_H_ */ diff --git a/gen_input/templates/llvm/src-CORENAME.cpp.gtl b/gen_input/templates/llvm/src-CORENAME.cpp.gtl deleted file mode 100644 index 8ed478f..0000000 --- a/gen_input/templates/llvm/src-CORENAME.cpp.gtl +++ /dev/null @@ -1,107 +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. - * - *******************************************************************************/ - <% -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 -#include -#include -#include -#include - -using namespace iss::arch; - -constexpr std::array iss::arch::traits::reg_names; -constexpr std::array iss::arch::traits::reg_aliases; -constexpr std::array iss::arch::traits::reg_bit_widths; -constexpr std::array iss::arch::traits::reg_byte_offsets; - -${coreDef.name.toLowerCase()}::${coreDef.name.toLowerCase()}() { - reg.icount = 0; -} - -${coreDef.name.toLowerCase()}::~${coreDef.name.toLowerCase()}() = default; - -void ${coreDef.name.toLowerCase()}::reset(uint64_t address) { - for(size_t i=0; i::NUM_REGS; ++i) set_reg(i, std::vector(sizeof(traits<${coreDef.name.toLowerCase()}>::reg_t),0)); - reg.PC=address; - reg.NEXT_PC=reg.PC; - reg.trap_state=0; - reg.machine_state=0x3; - reg.icount=0; -} - -uint8_t *${coreDef.name.toLowerCase()}::get_regs_base_ptr() { - return reinterpret_cast(®); -} - -${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 -} - diff --git a/gen_input/templates/tcc/vm-vm_CORENAME.cpp.gtl b/gen_input/templates/tcc/CORENAME.cpp.gtl similarity index 53% rename from gen_input/templates/tcc/vm-vm_CORENAME.cpp.gtl rename to gen_input/templates/tcc/CORENAME.cpp.gtl index 23c5dd0..252df3d 100644 --- a/gen_input/templates/tcc/vm-vm_CORENAME.cpp.gtl +++ b/gen_input/templates/tcc/CORENAME.cpp.gtl @@ -29,9 +29,8 @@ * POSSIBILITY OF SUCH DAMAGE. * *******************************************************************************/ - +// clang-format off #include -#include #include #include #include @@ -55,10 +54,12 @@ using namespace iss::debugger; template class vm_impl : public iss::tcc::vm_base { public: + using traits = arch::traits; using super = typename iss::tcc::vm_base; 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 mem_type_e = typename traits::mem_type_e; using addr_t = typename super::addr_t; using tu_builder = typename super::tu_builder; @@ -82,7 +83,7 @@ protected: using compile_ret_t = std::tuple; using compile_func = compile_ret_t (this_class::*)(virt_addr_t &pc, code_word_t instr, tu_builder&); - inline const char *name(size_t index){return traits::reg_aliases.at(index);} + inline const char *name(size_t index){return traits::reg_aliases.at(index);} void setup_module(std::string m) override { super::setup_module(m); @@ -104,10 +105,10 @@ protected: inline void gen_set_pc(tu_builder& tu, virt_addr_t pc, unsigned reg_num) { switch(reg_num){ - case traits::NEXT_PC: + case traits::NEXT_PC: tu("*next_pc = {:#x};", pc.val); break; - case traits::PC: + case traits::PC: tu("*pc = {:#x};", pc.val); break; default: @@ -119,79 +120,61 @@ protected: } } - // 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) }; - - std::array lut; - - std::array lut_00, lut_01, lut_10; - std::array lut_11; - - std::array qlut; - - std::array 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; - } + + template::type> + inline S sext(U from) { + auto mask = (1ULL< instrs; + std::vector children; + uint32_t submask = std::numeric_limits::max(); + uint32_t value; + decoding_tree_node(uint32_t value) : value(value){} + }; - const std::array instr_descr = {{ + decoding_tree_node* root {nullptr}; + + const std::array instr_descr = {{ /* entries are: size, valid value, valid mask, function ptr */<%instructions.each{instr -> %> /* instruction ${instr.instruction.name}, encoding '${instr.encoding}' */ - {${instr.length}, 0b${instr.value}, 0b${instr.mask}, &this_class::__${generator.functionName(instr.name)}},<%}%> + {${instr.length}, ${instr.encoding}, ${instr.mask}, &this_class::__${generator.functionName(instr.name)}},<%}%> }}; /* instruction definitions */<%instructions.eachWithIndex{instr, idx -> %> /* instruction ${idx}: ${instr.name} */ - compile_ret_t __${generator.functionName(instr.name)}(virt_addr_t& pc, code_word_t instr, tu_builder& tu){<%instr.code.eachLine{%> - ${it}<%}%> + compile_ret_t __${generator.functionName(instr.name)}(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("${instr.name}_{:#010x}:", pc.val); + vm_base::gen_sync(tu, PRE_SYNC,${idx}); + uint64_t PC = pc.val; + <%instr.fields.eachLine{%>${it} + <%}%>if(this->disass_enabled){ + /* generate console output when executing the command */<%instr.disass.eachLine{%> + ${it}<%}%> + } + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); + pc=pc+ ${instr.length/8}; + gen_set_pc(tu, pc, traits::NEXT_PC); + tu.open_scope(); + <%instr.behavior.eachLine{%>${it} + <%}%> + tu.close_scope(); + gen_trap_check(tu); + vm_base::gen_sync(tu, POST_SYNC,${idx}); + return returnValue; } <%}%> /**************************************************************************** @@ -205,11 +188,64 @@ private: vm_impl::gen_trap_check(tu); return BRANCH; } + + //decoding functionality + + void populate_decoding_tree(decoding_tree_node* root){ + //create submask + for(auto instr: root->instrs){ + root->submask &= instr.mask; + } + //put each instr according to submask&encoding into children + for(auto instr: root->instrs){ + bool foundMatch = false; + for(auto child: root->children){ + //use value as identifying trait + if(child->value == (instr.value&root->submask)){ + child->instrs.push_back(instr); + foundMatch = true; + } + } + if(!foundMatch){ + decoding_tree_node* child = new decoding_tree_node(instr.value&root->submask); + child->instrs.push_back(instr); + root->children.push_back(child); + } + } + root->instrs.clear(); + //call populate_decoding_tree for all children + if(root->children.size() >1) + for(auto child: root->children){ + populate_decoding_tree(child); + } + else{ + //sort instrs by value of the mask, this works bc we want to have the least restrictive one last + std::sort(root->children[0]->instrs.begin(), root->children[0]->instrs.end(), [](const instruction_descriptor& instr1, const instruction_descriptor& instr2) { + return instr1.mask > instr2.mask; + }); + } + } + compile_func decode_instr(decoding_tree_node* node, code_word_t word){ + if(!node->children.size()){ + if(node->instrs.size() == 1) return node->instrs[0].op; + for(auto instr : node->instrs){ + if((instr.mask&word) == instr.value) return instr.op; + } + } + else{ + for(auto child : node->children){ + if (child->value == (node->submask&word)){ + return decode_instr(child, word); + } + } + } + return nullptr; + } }; -template void debug_fn(CODE_WORD insn) { - volatile CODE_WORD x = insn; - insn = 2 * x; +template void debug_fn(CODE_WORD instr) { + volatile CODE_WORD x = instr; + instr = 2 * x; } template vm_impl::vm_impl() { this(new ARCH()); } @@ -217,14 +253,11 @@ template vm_impl::vm_impl() { this(new ARCH()); } template vm_impl::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id) : vm_base(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); + root = new decoding_tree_node(std::numeric_limits::max()); + for(auto instr:instr_descr){ + root->instrs.push_back(instr); } + populate_decoding_tree(root); } template @@ -232,41 +265,40 @@ std::tuple vm_impl::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, tu_builder& tu) { // we fetch at max 4 byte, alignment is 2 enum {TRAP_ID=1<<16}; - code_word_t insn = 0; - const typename traits::addr_t upper_bits = ~traits::PGMASK; + code_word_t instr = 0; phys_addr_t paddr(pc); - 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(this->core.has_mmu()) + paddr = this->core.virt2phys(pc); + //TODO: re-add page handling +// 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); +// } +// } else { + auto res = this->core.read(paddr, 4, reinterpret_cast(&instr)); 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); - } - } 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' +// } + if (instr == 0x0000006f || (instr&0xffff)==0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0' // curr pc on stack ++inst_cnt; - auto lut_val = extract_fields(insn); - auto f = qlut[insn & 0x3][lut_val]; + auto f = decode_instr(root, instr); if (f == nullptr) { f = &this_class::illegal_intruction; } - return (this->*f)(pc, insn, tu); + return (this->*f)(pc, instr, tu); } template void vm_impl::gen_raise_trap(tu_builder& tu, uint16_t trap_id, uint16_t cause) { tu(" *trap_state = {:#x};", 0x80 << 24 | (cause << 16) | trap_id); - tu.store(tu.constant(std::numeric_limits::max(), 32),traits::LAST_BRANCH); + tu.store(traits::LAST_BRANCH, tu.constant(std::numeric_limits::max(), 32)); } template void vm_impl::gen_leave_trap(tu_builder& tu, unsigned lvl) { tu("leave_trap(core_ptr, {});", lvl); - tu.store(tu.read_mem(traits::CSR, (lvl << 8) + 0x41, traits::XLEN),traits::NEXT_PC); - tu.store(tu.constant(std::numeric_limits::max(), 32),traits::LAST_BRANCH); + tu.store(traits::NEXT_PC, tu.read_mem(traits::CSR, (lvl << 8) + 0x41, traits::XLEN)); + tu.store(traits::LAST_BRANCH, tu.constant(std::numeric_limits::max(), 32)); } template void vm_impl::gen_wait(tu_builder& tu, unsigned type) { @@ -274,12 +306,13 @@ template void vm_impl::gen_wait(tu_builder& tu, unsigned t template void vm_impl::gen_trap_behavior(tu_builder& tu) { tu("trap_entry:"); - tu("enter_trap(core_ptr, *trap_state, *pc);"); - tu.store(tu.constant(std::numeric_limits::max(),32),traits::LAST_BRANCH); + this->gen_sync(tu, POST_SYNC, -1); + tu("enter_trap(core_ptr, *trap_state, *pc, 0);"); + tu.store(traits::LAST_BRANCH, tu.constant(std::numeric_limits::max(),32)); tu("return *next_pc;"); } -} // namespace mnrv32 +} // namespace ${coreDef.name.toLowerCase()} template <> std::unique_ptr create(arch::${coreDef.name.toLowerCase()} *core, unsigned short port, bool dump) { @@ -287,5 +320,28 @@ std::unique_ptr create(arch::${coreD if (port != 0) debugger::server::run_server(ret, port); return std::unique_ptr(ret); } -} +} // namesapce tcc } // namespace iss + +#include +#include +#include +namespace iss { +namespace { +volatile std::array dummy = { + core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|m_p|tcc", [](unsigned port, void*) -> std::tuple{ + auto* cpu = new iss::arch::riscv_hart_m_p(); + auto vm = new tcc::${coreDef.name.toLowerCase()}::vm_impl(*cpu, false); + if (port != 0) debugger::server::run_server(vm, port); + return {cpu_ptr{cpu}, vm_ptr{vm}}; + }), + core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p|tcc", [](unsigned port, void*) -> std::tuple{ + auto* cpu = new iss::arch::riscv_hart_mu_p(); + auto vm = new tcc::${coreDef.name.toLowerCase()}::vm_impl(*cpu, false); + if (port != 0) debugger::server::run_server(vm, port); + return {cpu_ptr{cpu}, vm_ptr{vm}}; + }) +}; +} +} +// clang-format on \ No newline at end of file diff --git a/gen_input/templates/tcc/CORENAME_cyles.txt.gtl b/gen_input/templates/tcc/CORENAME_cyles.txt.gtl deleted file mode 100644 index 3a1ad8e..0000000 --- a/gen_input/templates/tcc/CORENAME_cyles.txt.gtl +++ /dev/null @@ -1,9 +0,0 @@ -{ - "${coreDef.name}" : [<%instructions.eachWithIndex{instr,index -> %>${index==0?"":","} - { - "name" : "${instr.name}", - "size" : ${instr.length}, - "delay" : ${generator.hasAttribute(instr.instruction, com.minres.coredsl.coreDsl.InstrAttribute.COND)?[1,1]:1} - }<%}%> - ] -} \ No newline at end of file diff --git a/gen_input/templates/tcc/incl-CORENAME.h.gtl b/gen_input/templates/tcc/incl-CORENAME.h.gtl deleted file mode 100644 index 0a5b99f..0000000 --- a/gen_input/templates/tcc/incl-CORENAME.h.gtl +++ /dev/null @@ -1,223 +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. - * - *******************************************************************************/ - -<% -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 -#include -#include -#include - -namespace iss { -namespace arch { - -struct ${coreDef.name.toLowerCase()}; - -template <> struct traits<${coreDef.name.toLowerCase()}> { - - constexpr static char const* const core_type = "${coreDef.name}"; - - static constexpr std::array reg_names{ - {"${getRegisterNames().join("\", \"")}"}}; - - static constexpr std::array 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}; - - enum reg_e {<% - allRegs.each { reg -> - if( reg instanceof RegisterFile) { - (reg.range.right..reg.range.left).each{%> - ${reg.name}${it},<% - } - } else if(reg instanceof Register){ %> - ${reg.name},<% - } - }%> - NUM_REGS, - NEXT_${pc.name}=NUM_REGS, - TRAP_STATE, - PENDING_TRAP, - MACHINE_STATE, - LAST_BRANCH, - ICOUNT<% - allRegs.each { reg -> - if(reg instanceof RegisterAlias){ def aliasname=getOriginalName(reg)%>, - ${reg.name} = ${aliasname}<% - } - }%> - }; - - using reg_t = uint${regDataWidth}_t; - - using addr_t = uint${addrDataWidth}_t; - - using code_word_t = uint${addrDataWidth}_t; //TODO: check removal - - using virt_addr_t = iss::typed_addr_t; - - using phys_addr_t = iss::typed_addr_t; - - static constexpr std::array reg_bit_widths{ - {${regSizes.join(",")}}}; - - static constexpr std::array 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 mem_type_e { ${allSpaces.collect{s -> s.name}.join(', ')} }; -}; - -struct ${coreDef.name.toLowerCase()}: public arch_if { - - using virt_addr_t = typename traits<${coreDef.name.toLowerCase()}>::virt_addr_t; - using phys_addr_t = typename traits<${coreDef.name.toLowerCase()}>::phys_addr_t; - using reg_t = typename traits<${coreDef.name.toLowerCase()}>::reg_t; - using addr_t = typename traits<${coreDef.name.toLowerCase()}>::addr_t; - - ${coreDef.name.toLowerCase()}(); - ~${coreDef.name.toLowerCase()}(); - - void reset(uint64_t address=0) override; - - uint8_t* get_regs_base_ptr() override; - /// deprecated - void get_reg(short idx, std::vector& value) override {} - void set_reg(short idx, const std::vector& 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 uint64_t stop_code() { 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(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); - } - - 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 ${coreDef.name}_regs {<% - allRegs.each { reg -> - if( reg instanceof RegisterFile) { - (reg.range.right..reg.range.left).each{%> - uint${generator.getSize(reg)}_t ${reg.name}${it} = 0;<% - } - } else if(reg instanceof Register){ %> - uint${generator.getSize(reg)}_t ${reg.name} = 0;<% - } - }%> - uint${generator.getSize(pc)}_t NEXT_${pc.name} = 0; - uint32_t trap_state = 0, pending_trap = 0, machine_state = 0, last_branch = 0; - uint64_t icount = 0; - } reg; - - std::array addr_mode; - - uint64_t interrupt_sim=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){} -<%}%> -}; - -} -} -#endif /* _${coreDef.name.toUpperCase()}_H_ */ diff --git a/gen_input/templates/tcc/src-CORENAME.cpp.gtl b/gen_input/templates/tcc/src-CORENAME.cpp.gtl deleted file mode 100644 index 8ed478f..0000000 --- a/gen_input/templates/tcc/src-CORENAME.cpp.gtl +++ /dev/null @@ -1,107 +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. - * - *******************************************************************************/ - <% -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 -#include -#include -#include -#include - -using namespace iss::arch; - -constexpr std::array iss::arch::traits::reg_names; -constexpr std::array iss::arch::traits::reg_aliases; -constexpr std::array iss::arch::traits::reg_bit_widths; -constexpr std::array iss::arch::traits::reg_byte_offsets; - -${coreDef.name.toLowerCase()}::${coreDef.name.toLowerCase()}() { - reg.icount = 0; -} - -${coreDef.name.toLowerCase()}::~${coreDef.name.toLowerCase()}() = default; - -void ${coreDef.name.toLowerCase()}::reset(uint64_t address) { - for(size_t i=0; i::NUM_REGS; ++i) set_reg(i, std::vector(sizeof(traits<${coreDef.name.toLowerCase()}>::reg_t),0)); - reg.PC=address; - reg.NEXT_PC=reg.PC; - reg.trap_state=0; - reg.machine_state=0x3; - reg.icount=0; -} - -uint8_t *${coreDef.name.toLowerCase()}::get_regs_base_ptr() { - return reinterpret_cast(®); -} - -${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 -} - diff --git a/incl/iss/arch/.gitignore b/incl/iss/arch/.gitignore deleted file mode 100644 index 52334de..0000000 --- a/incl/iss/arch/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/tgc_*.h diff --git a/incl/iss/arch/riscv_hart_m_p.h b/incl/iss/arch/riscv_hart_m_p.h deleted file mode 100644 index bff635d..0000000 --- a/incl/iss/arch/riscv_hart_m_p.h +++ /dev/null @@ -1,1217 +0,0 @@ -/******************************************************************************* - * Copyright (C) 2021 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 implementation - ******************************************************************************/ - -#ifndef _RISCV_HART_M_P_H -#define _RISCV_HART_M_P_H - -#include "riscv_hart_common.h" -#include "iss/arch/traits.h" -#include "iss/instrumentation_if.h" -#include "iss/log_categories.h" -#include "iss/vm_if.h" -#ifndef FMT_HEADER_ONLY -#define FMT_HEADER_ONLY -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if defined(__GNUC__) -#define likely(x) __builtin_expect(!!(x), 1) -#define unlikely(x) __builtin_expect(!!(x), 0) -#else -#define likely(x) x -#define unlikely(x) x -#endif - -namespace iss { -namespace arch { - -template class riscv_hart_m_p : public BASE { -protected: - const std::array lvl = {{'U', 'S', 'H', 'M'}}; - const std::array trap_str = {{"" - "Instruction address misaligned", // 0 - "Instruction access fault", // 1 - "Illegal instruction", // 2 - "Breakpoint", // 3 - "Load address misaligned", // 4 - "Load access fault", // 5 - "Store/AMO address misaligned", // 6 - "Store/AMO access fault", // 7 - "Environment call from U-mode", // 8 - "Environment call from S-mode", // 9 - "Reserved", // a - "Environment call from M-mode", // b - "Instruction page fault", // c - "Load page fault", // d - "Reserved", // e - "Store/AMO page fault"}}; - const std::array irq_str = { - {"User software interrupt", "Supervisor software interrupt", "Reserved", "Machine software interrupt", - "User timer interrupt", "Supervisor timer interrupt", "Reserved", "Machine timer interrupt", - "User external interrupt", "Supervisor external interrupt", "Reserved", "Machine external interrupt"}}; -public: - using core = BASE; - using this_class = riscv_hart_m_p; - using phys_addr_t = typename core::phys_addr_t; - using reg_t = typename core::reg_t; - using addr_t = typename core::addr_t; - - using rd_csr_f = iss::status (this_class::*)(unsigned addr, reg_t &); - using wr_csr_f = iss::status (this_class::*)(unsigned addr, reg_t); - using mem_read_f = iss::status(phys_addr_t addr, unsigned, uint8_t *const); - using mem_write_f = iss::status(phys_addr_t addr, unsigned, uint8_t const *const); - - // primary template - template struct hart_state {}; - // specialization 32bit - template class hart_state::value>::type> { - public: - BEGIN_BF_DECL(mstatus_t, T); - // SD bit is read-only and is set when either the FS or XS bits encode a Dirty state (i.e., SD=((FS==11) OR XS==11))) - BF_FIELD(SD, 31, 1); - // Trap SRET - BF_FIELD(TSR, 22, 1); - // Timeout Wait - BF_FIELD(TW, 21, 1); - // Trap Virtual Memory - BF_FIELD(TVM, 20, 1); - // Make eXecutable Readable - BF_FIELD(MXR, 19, 1); - // permit Supervisor User Memory access - BF_FIELD(SUM, 18, 1); - // Modify PRiVilege - BF_FIELD(MPRV, 17, 1); - // status of additional user-mode extensions and associated state, All off/None dirty or clean, some on/None dirty, some clean/Some dirty - BF_FIELD(XS, 15, 2); - // floating-point unit status Off/Initial/Clean/Dirty - BF_FIELD(FS, 13, 2); - // machine previous privilege - BF_FIELD(MPP, 11, 2); - // supervisor previous privilege - BF_FIELD(SPP, 8, 1); - // previous machine interrupt-enable - BF_FIELD(MPIE, 7, 1); - // previous supervisor interrupt-enable - BF_FIELD(SPIE, 5, 1); - // previous user interrupt-enable - BF_FIELD(UPIE, 4, 1); - // machine interrupt-enable - BF_FIELD(MIE, 3, 1); - // supervisor interrupt-enable - BF_FIELD(SIE, 1, 1); - // user interrupt-enable - BF_FIELD(UIE, 0, 1); - END_BF_DECL(); - - mstatus_t mstatus; - - static const reg_t mstatus_reset_val = 0x1800; - - void write_mstatus(T val) { - auto mask = get_mask() &0xff; // MPP is hardcode as 0x3 - auto new_val = (mstatus.backing.val & ~mask) | (val & mask); - mstatus = new_val; - } - - static constexpr uint32_t get_mask() { - //return 0x807ff988UL; // 0b1000 0000 0111 1111 1111 1000 1000 1000 // only machine mode is supported - // +-SD - // | +-TSR - // | |+-TW - // | ||+-TVM - // | |||+-MXR - // | ||||+-SUM - // | |||||+-MPRV - // | |||||| +-XS - // | |||||| | +-FS - // | |||||| | | +-MPP - // | |||||| | | | +-SPP - // | |||||| | | | |+-MPIE - // | ||||||/|/|/| || +-MIE - return 0b00000000000000000001100010001000; - } - }; - using hart_state_type = hart_state; - - constexpr reg_t get_irq_mask() { - return 0b100010001000; // only machine mode is supported - } - - constexpr reg_t get_pc_mask() { - return traits::MISA_VAL&0b0100?~1:~3; - } - - riscv_hart_m_p(); - virtual ~riscv_hart_m_p() = default; - - void reset(uint64_t address) override; - - std::pair load_file(std::string name, int type = -1) override; - - iss::status read(const address_type type, const access_type access, const uint32_t space, - const uint64_t addr, const unsigned length, uint8_t *const data) override; - iss::status write(const address_type type, const access_type access, const uint32_t space, - const uint64_t addr, const unsigned length, const uint8_t *const data) override; - - virtual uint64_t enter_trap(uint64_t flags) override { return riscv_hart_m_p::enter_trap(flags, fault_data, fault_data); } - virtual uint64_t enter_trap(uint64_t flags, uint64_t addr, uint64_t instr) override; - virtual uint64_t leave_trap(uint64_t flags) override; - - const reg_t& get_mhartid() const { return mhartid_reg; } - void set_mhartid(reg_t mhartid) { mhartid_reg = mhartid; }; - - void disass_output(uint64_t pc, const std::string instr) override { - CLOG(INFO, disass) << fmt::format("0x{:016x} {:40} [s:0x{:x};c:{}]", - pc, instr, (reg_t)state.mstatus, this->reg.icount + cycle_offset); - }; - - iss::instrumentation_if *get_instrumentation_if() override { return &instr_if; } - - void setMemReadCb(std::function const& memReadCb) { - mem_read_cb = memReadCb; - } - - void setMemWriteCb(std::function const& memWriteCb) { - mem_write_cb = memWriteCb; - } - - void set_csr(unsigned addr, reg_t val){ - csr[addr & csr.page_addr_mask] = val; - } - - void set_irq_num(unsigned i) { - mcause_max_irq=1< &arch) - : arch(arch) {} - /** - * get the name of this architecture - * - * @return the name of this architecture - */ - const std::string core_type_name() const override { return traits::core_type; } - - uint64_t get_pc() override { return arch.get_pc(); }; - - uint64_t get_next_pc() override { return arch.get_next_pc(); }; - - uint64_t get_instr_count() { return arch.reg.icount; } - - uint64_t get_total_cycles() override { return arch.reg.icount + arch.cycle_offset; } - - void set_curr_instr_cycles(unsigned cycles) override { arch.cycle_offset += cycles - 1; }; - - riscv_hart_m_p &arch; - }; - - friend struct riscv_instrumentation_if; - addr_t get_pc() { return this->reg.PC; } - addr_t get_next_pc() { return this->reg.NEXT_PC; } - - virtual iss::status read_mem(phys_addr_t addr, unsigned length, uint8_t *const data); - virtual iss::status write_mem(phys_addr_t addr, unsigned length, const uint8_t *const data); - - iss::status read_clic(uint64_t addr, unsigned length, uint8_t *const data); - iss::status write_clic(uint64_t addr, unsigned length, const uint8_t *const data); - - virtual iss::status read_csr(unsigned addr, reg_t &val); - virtual iss::status write_csr(unsigned addr, reg_t val); - - hart_state_type state; - int64_t cycle_offset{0}; - uint64_t mcycle_csr{0}; - int64_t instret_offset{0}; - uint64_t minstret_csr{0}; - reg_t fault_data; - uint64_t tohost = tohost_dflt; - uint64_t fromhost = fromhost_dflt; - unsigned to_host_wr_cnt = 0; - riscv_instrumentation_if instr_if; - - using mem_type = util::sparse_array; - using csr_type = util::sparse_array::reg_t, 1ULL << 12, 12>; - using csr_page_type = typename csr_type::page_type; - mem_type mem; - csr_type csr; - std::stringstream uart_buf; - std::unordered_map ptw; - std::unordered_map atomic_reservation; - std::unordered_map csr_rd_cb; - std::unordered_map csr_wr_cb; - uint8_t clic_cfg_reg{0}; - uint32_t clic_info_reg{0}; - std::array clic_inttrig_reg; - union clic_int_reg_t { - struct{ - uint8_t ip; - uint8_t ie; - uint8_t attr; - uint8_t ctl; - }; - uint32_t raw; - }; - std::vector clic_int_reg; - - std::vector tcm; - - iss::status read_csr_reg(unsigned addr, reg_t &val); - iss::status write_csr_reg(unsigned addr, reg_t val); - iss::status read_null(unsigned addr, reg_t &val); - iss::status write_null(unsigned addr, reg_t val){return iss::status::Ok;} - iss::status read_cycle(unsigned addr, reg_t &val); - iss::status write_cycle(unsigned addr, reg_t val); - iss::status read_instret(unsigned addr, reg_t &val); - iss::status write_instret(unsigned addr, reg_t val); - iss::status read_tvec(unsigned addr, reg_t &val); - iss::status read_time(unsigned addr, reg_t &val); - iss::status read_status(unsigned addr, reg_t &val); - iss::status write_status(unsigned addr, reg_t val); - iss::status write_cause(unsigned addr, reg_t val); - iss::status read_ie(unsigned addr, reg_t &val); - iss::status write_ie(unsigned addr, reg_t val); - iss::status read_ip(unsigned addr, reg_t &val); - iss::status read_hartid(unsigned addr, reg_t &val); - iss::status write_epc(unsigned addr, reg_t val); - iss::status write_intstatus(unsigned addr, reg_t val); - iss::status write_intthresh(unsigned addr, reg_t val); - iss::status write_dcsr_dcsr(unsigned addr, reg_t val); - iss::status read_dcsr_reg(unsigned addr, reg_t &val); - iss::status write_dcsr_reg(unsigned addr, reg_t val); - iss::status read_dpc_reg(unsigned addr, reg_t &val); - iss::status write_dpc_reg(unsigned addr, reg_t val); - - virtual iss::status read_custom_csr_reg(unsigned addr, reg_t &val) {return iss::status::Err;}; - virtual iss::status write_custom_csr_reg(unsigned addr, reg_t val) {return iss::status::Err;}; - - void register_custom_csr_rd(unsigned addr){ - csr_rd_cb[addr] = &this_class::read_custom_csr_reg; - } - void register_custom_csr_wr(unsigned addr){ - csr_wr_cb[addr] = &this_class::write_custom_csr_reg; - } - - reg_t mhartid_reg{0x0}; - std::functionmem_read_cb; - std::function mem_write_cb; - - void check_interrupt(); - bool pmp_check(const access_type type, const uint64_t addr, const unsigned len); - std::vector> memfn_range; - std::vector> memfn_read; - std::vector> memfn_write; - void insert_mem_range(uint64_t, uint64_t, std::function, std::function); - uint64_t clic_base_addr{0}; - unsigned clic_num_irq{0}; - unsigned clic_num_trigger{0}; - unsigned mcause_max_irq{16}; - inline bool debug_mode_active() {return this->reg.PRIV&0x4;} -}; - -template -riscv_hart_m_p::riscv_hart_m_p() -: state() -, instr_if(*this) { - // reset values - csr[misa] = traits::MISA_VAL; - csr[mvendorid] = 0x669; - csr[marchid] = traits::MARCHID_VAL; - csr[mimpid] = 1; - csr[mclicbase] = 0xc0000000; // TODO: should be taken from YAML file - - uart_buf.str(""); - for (unsigned addr = mhpmcounter3; addr <= mhpmcounter31; ++addr){ - csr_rd_cb[addr] = &this_class::read_null; - csr_wr_cb[addr] = &this_class::write_csr_reg; - } - for (unsigned addr = mhpmcounter3h; addr <= mhpmcounter31h; ++addr){ - csr_rd_cb[addr] = &this_class::read_null; - csr_wr_cb[addr] = &this_class::write_csr_reg; - } - for (unsigned addr = mhpmevent3; addr <= mhpmevent31; ++addr){ - csr_rd_cb[addr] = &this_class::read_null; - csr_wr_cb[addr] = &this_class::write_csr_reg; - } - for (unsigned addr = hpmcounter3; addr <= hpmcounter31; ++addr){ - csr_rd_cb[addr] = &this_class::read_null; - } - for (unsigned addr = hpmcounter3h; addr <= hpmcounter31h; ++addr){ - csr_rd_cb[addr] = &this_class::read_null; - //csr_wr_cb[addr] = &this_class::write_csr_reg; - } - // common regs - const std::array addrs{{misa, mvendorid, marchid, mimpid, mepc, mtvec, mscratch, mcause, mtval, mscratch}}; - for(auto addr: addrs) { - csr_rd_cb[addr] = &this_class::read_csr_reg; - csr_wr_cb[addr] = &this_class::write_csr_reg; - } - // special handling & overrides - csr_rd_cb[time] = &this_class::read_time; - csr_rd_cb[timeh] = &this_class::read_time; - csr_rd_cb[cycle] = &this_class::read_cycle; - csr_rd_cb[cycleh] = &this_class::read_cycle; - csr_rd_cb[instret] = &this_class::read_instret; - csr_rd_cb[instreth] = &this_class::read_instret; - - csr_rd_cb[mcycle] = &this_class::read_cycle; - csr_wr_cb[mcycle] = &this_class::write_cycle; - csr_rd_cb[mcycleh] = &this_class::read_cycle; - csr_wr_cb[mcycleh] = &this_class::write_cycle; - csr_rd_cb[minstret] = &this_class::read_instret; - csr_wr_cb[minstret] = &this_class::write_instret; - csr_rd_cb[minstreth] = &this_class::read_instret; - csr_wr_cb[minstreth] = &this_class::write_instret; - csr_rd_cb[mstatus] = &this_class::read_status; - csr_wr_cb[mstatus] = &this_class::write_status; - csr_wr_cb[mcause] = &this_class::write_cause; - csr_rd_cb[mtvec] = &this_class::read_tvec; - csr_wr_cb[mepc] = &this_class::write_epc; - csr_rd_cb[mip] = &this_class::read_ip; - csr_wr_cb[mip] = &this_class::write_null; - csr_rd_cb[mie] = &this_class::read_ie; - csr_wr_cb[mie] = &this_class::write_ie; - csr_rd_cb[mhartid] = &this_class::read_hartid; - csr_wr_cb[misa] = &this_class::write_null; - csr_wr_cb[mvendorid] = &this_class::write_null; - csr_wr_cb[marchid] = &this_class::write_null; - csr_wr_cb[mimpid] = &this_class::write_null; - if(FEAT & FEAT_CLIC) { - csr_rd_cb[mtvt] = &this_class::read_csr_reg; - csr_wr_cb[mtvt] = &this_class::write_csr_reg; - csr_rd_cb[mxnti] = &this_class::read_csr_reg; - csr_wr_cb[mxnti] = &this_class::write_csr_reg; - csr_rd_cb[mintstatus] = &this_class::read_csr_reg; - csr_wr_cb[mintstatus] = &this_class::write_null; - csr_rd_cb[mscratchcsw] = &this_class::read_csr_reg; - csr_wr_cb[mscratchcsw] = &this_class::write_csr_reg; - csr_rd_cb[mscratchcswl] = &this_class::read_csr_reg; - csr_wr_cb[mscratchcswl] = &this_class::write_csr_reg; - csr_rd_cb[mintthresh] = &this_class::read_csr_reg; - csr_wr_cb[mintthresh] = &this_class::write_intthresh; - csr_rd_cb[mclicbase] = &this_class::read_csr_reg; - csr_wr_cb[mclicbase] = &this_class::write_null; - - clic_base_addr=0xC0000000; - clic_num_irq=16; - clic_int_reg.resize(clic_num_irq); - clic_cfg_reg=0x20; - clic_info_reg = (/*CLICINTCTLBITS*/ 4U<<21) + clic_num_irq; - mcause_max_irq=clic_num_irq+16; - insert_mem_range(clic_base_addr, 0x5000UL, - [this](phys_addr_t addr, unsigned length, uint8_t * const data) { return read_clic(addr.val, length, data);}, - [this](phys_addr_t addr, unsigned length, uint8_t const * const data) {return write_clic(addr.val, length, data);}); - } - if(FEAT & FEAT_TCM) { - tcm.resize(0x8000); - std::function read_clic_cb = [this](phys_addr_t addr, unsigned length, uint8_t * const data) { - auto offset=addr.val-0x10000000; - std::copy(tcm.data() + offset, tcm.data() + offset + length, data); - return iss::Ok; - }; - std::function write_clic_cb = [this](phys_addr_t addr, unsigned length, uint8_t const * const data) { - auto offset=addr.val-0x10000000; - std::copy(data, data + length, tcm.data() + offset); - return iss::Ok; - }; - insert_mem_range(0x10000000, 0x8000UL, read_clic_cb, write_clic_cb); - } - if(FEAT & FEAT_DEBUG){ - csr_wr_cb[dscratch0] = &this_class::write_dcsr_reg; - csr_rd_cb[dscratch0] = &this_class::read_dcsr_reg; - csr_wr_cb[dscratch1] = &this_class::write_dcsr_reg; - csr_rd_cb[dscratch1] = &this_class::read_dcsr_reg; - csr_wr_cb[dpc] = &this_class::write_dpc_reg; - csr_rd_cb[dpc] = &this_class::read_dpc_reg; - csr_wr_cb[dcsr] = &this_class::write_dcsr_dcsr; - csr_rd_cb[dcsr] = &this_class::read_dcsr_reg; - } -} - -template std::pair riscv_hart_m_p::load_file(std::string name, int type) { - FILE *fp = fopen(name.c_str(), "r"); - if (fp) { - std::array buf; - auto n = fread(buf.data(), 1, 4, fp); - if (n != 4) throw std::runtime_error("input file has insufficient size"); - buf[4] = 0; - if (strcmp(buf.data() + 1, "ELF") == 0) { - fclose(fp); - // Create elfio reader - ELFIO::elfio reader; - // Load ELF data - if (!reader.load(name)) throw std::runtime_error("could not process elf file"); - // check elf properties - if (reader.get_class() != ELFCLASS32) - if (sizeof(reg_t) == 4) throw std::runtime_error("wrong elf class in file"); - if (reader.get_type() != ET_EXEC) throw std::runtime_error("wrong elf type in file"); - if (reader.get_machine() != EM_RISCV) throw std::runtime_error("wrong elf machine in file"); - auto entry = reader.get_entry(); - for (const auto pseg : reader.segments) { - const auto fsize = pseg->get_file_size(); // 0x42c/0x0 - const auto seg_data = pseg->get_data(); - if (fsize > 0) { - auto res = this->write(iss::address_type::PHYSICAL, iss::access_type::DEBUG_WRITE, - traits::MEM, pseg->get_physical_address(), - fsize, reinterpret_cast(seg_data)); - if (res != iss::Ok) - LOG(ERR) << "problem writing " << fsize << "bytes to 0x" << std::hex - << pseg->get_physical_address(); - } - } - for(const auto sec : reader.sections) { - if(sec->get_name() == ".symtab") { - if ( SHT_SYMTAB == sec->get_type() || - SHT_DYNSYM == sec->get_type() ) { - ELFIO::symbol_section_accessor symbols( reader, sec ); - auto sym_no = symbols.get_symbols_num(); - std::string name; - ELFIO::Elf64_Addr value = 0; - ELFIO::Elf_Xword size = 0; - unsigned char bind = 0; - unsigned char type = 0; - ELFIO::Elf_Half section = 0; - unsigned char other = 0; - for ( auto i = 0U; i < sym_no; ++i ) { - symbols.get_symbol( i, name, value, size, bind, type, section, other ); - if(name=="tohost") { - tohost = value; - } else if(name=="fromhost") { - fromhost = value; - } - } - } - } else if (sec->get_name() == ".tohost") { - tohost = sec->get_address(); - fromhost = tohost + 0x40; - } - - } - return std::make_pair(entry, true); - } - throw std::runtime_error("memory load file is not a valid elf file"); - } - throw std::runtime_error("memory load file not found"); -} - -template -inline void riscv_hart_m_p::insert_mem_range(uint64_t base, uint64_t size, std::function rd_f, - std::function wr_fn) { - std::tuple entry{base, size}; - auto it = std::upper_bound( memfn_range.begin(), memfn_range.end(), entry, - [](std::tuple const& a, std::tuple const& b){ - return std::get<0>(a)(b); - }); - auto idx = std::distance(memfn_range.begin(), it); - memfn_range.insert(it, entry); - memfn_read.insert(std::begin(memfn_read)+idx, rd_f); - memfn_write.insert(std::begin(memfn_write)+idx, wr_fn); -} - -template -iss::status riscv_hart_m_p::read(const address_type type, const access_type access, const uint32_t space, - const uint64_t addr, const unsigned length, uint8_t *const data) { -#ifndef NDEBUG - if (access && iss::access_type::DEBUG) { - LOG(TRACEALL) << "debug read of " << length << " bytes @addr 0x" << std::hex << addr; - } else if(access && iss::access_type::FETCH){ - LOG(TRACEALL) << "fetch of " << length << " bytes @addr 0x" << std::hex << addr; - } else { - LOG(TRACE) << "read of " << length << " bytes @addr 0x" << std::hex << addr; - } -#endif - try { - switch (space) { - case traits::MEM: { - if (unlikely((access == iss::access_type::FETCH || access == iss::access_type::DEBUG_FETCH) && (addr & 0x1) == 1)) { - fault_data = addr; - if (access && iss::access_type::DEBUG) throw trap_access(0, addr); - this->reg.trap_state = (1 << 31); // issue trap 0 - return iss::Err; - } - try { - auto alignment = access == iss::access_type::FETCH? (traits::MISA_VAL&0x100? 2 : 4) : length; - if(alignment>1 && (addr&(alignment-1))){ - this->reg.trap_state = 1<<31 | 4<<16; - fault_data=addr; - return iss::Err; - } - auto phys_addr = type==iss::address_type::PHYSICAL?phys_addr_t{access, space, addr}:BASE::v2p(iss::addr_t{access, type, space, addr}); - auto res = iss::Err; - if(access != access_type::FETCH && memfn_range.size()){ - auto it = std::find_if(std::begin(memfn_range), std::end(memfn_range), [phys_addr](std::tuple const& a){ - return std::get<0>(a)<=phys_addr.val && (std::get<0>(a)+std::get<1>(a))>phys_addr.val; - }); - if(it!=std::end(memfn_range)) { - auto idx = std::distance(std::begin(memfn_range), it); - res = memfn_read[idx](phys_addr, length, data); - } else - res = read_mem( phys_addr, length, data); - } else { - res = read_mem( phys_addr, length, data); - } - if (unlikely(res != iss::Ok)){ - this->reg.trap_state = (1 << 31) | (5 << 16); // issue trap 5 (load access fault - fault_data=addr; - } - return res; - } catch (trap_access &ta) { - this->reg.trap_state = (1 << 31) | ta.id; - fault_data=ta.addr; - return iss::Err; - } - } break; - case traits::CSR: { - if (length != sizeof(reg_t)) return iss::Err; - return read_csr(addr, *reinterpret_cast(data)); - } break; - case traits::FENCE: { - if ((addr + length) > mem.size()) return iss::Err; - return iss::Ok; - } break; - case traits::RES: { - auto it = atomic_reservation.find(addr); - if (it != atomic_reservation.end() && it->second != 0) { - memset(data, 0xff, length); - atomic_reservation.erase(addr); - } else - memset(data, 0, length); - } break; - default: - return iss::Err; // assert("Not supported"); - } - return iss::Ok; - } catch (trap_access &ta) { - this->reg.trap_state = (1 << 31) | ta.id; - fault_data=ta.addr; - return iss::Err; - } -} - -template -iss::status riscv_hart_m_p::write(const address_type type, const access_type access, const uint32_t space, - const uint64_t addr, const unsigned length, const uint8_t *const data) { -#ifndef NDEBUG - const char *prefix = (access && iss::access_type::DEBUG) ? "debug " : ""; - switch (length) { - case 8: - LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint64_t *)&data[0] << std::dec - << ") @addr 0x" << std::hex << addr; - break; - case 4: - LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint32_t *)&data[0] << std::dec - << ") @addr 0x" << std::hex << addr; - break; - case 2: - LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint16_t *)&data[0] << std::dec - << ") @addr 0x" << std::hex << addr; - break; - case 1: - LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << (uint16_t)data[0] << std::dec - << ") @addr 0x" << std::hex << addr; - break; - default: - LOG(TRACE) << prefix << "write of " << length << " bytes @addr " << addr; - } -#endif - try { - switch (space) { - case traits::MEM: { - if (unlikely((access && iss::access_type::FETCH) && (addr & 0x1) == 1)) { - fault_data = addr; - if (access && iss::access_type::DEBUG) throw trap_access(0, addr); - this->reg.trap_state = (1 << 31); // issue trap 0 - return iss::Err; - } - try { - if(length>1 && (addr&(length-1)) && (access&access_type::DEBUG) != access_type::DEBUG){ - this->reg.trap_state = 1<<31 | 6<<16; - fault_data=addr; - return iss::Err; - } - auto phys_addr = type==iss::address_type::PHYSICAL?phys_addr_t{access, space, addr}:BASE::v2p(iss::addr_t{access, type, space, addr}); - auto res = iss::Err; - if(access != access_type::FETCH && memfn_range.size()){ - auto it = std::find_if(std::begin(memfn_range), std::end(memfn_range), [phys_addr](std::tuple const& a){ - return std::get<0>(a)<=phys_addr.val && (std::get<0>(a)+std::get<1>(a))>phys_addr.val; - }); - if(it!=std::end(memfn_range)) { - auto idx = std::distance(std::begin(memfn_range), it); - res = memfn_write[idx]( phys_addr, length, data); - } else - res = write_mem( phys_addr, length, data); - } else { - res = write_mem( phys_addr, length, data); - } - if (unlikely(res != iss::Ok)) { - this->reg.trap_state = (1 << 31) | (7 << 16); // issue trap 7 (Store/AMO access fault) - fault_data=addr; - } - return res; - } catch (trap_access &ta) { - this->reg.trap_state = (1 << 31) | ta.id; - fault_data=ta.addr; - return iss::Err; - } - - phys_addr_t paddr = BASE::v2p(iss::addr_t{access, type, space, addr}); - if ((paddr.val + length) > mem.size()) return iss::Err; - switch (paddr.val) { - case 0x10013000: // UART0 base, TXFIFO reg - case 0x10023000: // UART1 base, TXFIFO reg - uart_buf << (char)data[0]; - if (((char)data[0]) == '\n' || data[0] == 0) { - // LOG(INFO)<<"UART"<<((paddr.val>>16)&0x3)<<" send - // '"<::CSR: { - if (length != sizeof(reg_t)) return iss::Err; - return write_csr(addr, *reinterpret_cast(data)); - } break; - case traits::FENCE: { - if ((addr + length) > mem.size()) return iss::Err; - switch (addr) { - case 2: - case 3: { - ptw.clear(); - auto tvm = state.mstatus.TVM; - return iss::Ok; - } - } - } break; - case traits::RES: { - atomic_reservation[addr] = data[0]; - } break; - default: - return iss::Err; - } - return iss::Ok; - } catch (trap_access &ta) { - this->reg.trap_state = (1 << 31) | ta.id; - fault_data=ta.addr; - return iss::Err; - } -} - -template iss::status riscv_hart_m_p::read_csr(unsigned addr, reg_t &val) { - if (addr >= csr.size()) return iss::Err; - auto req_priv_lvl = (addr >> 8) & 0x3; - if (this->reg.PRIV < req_priv_lvl) // not having required privileges - throw illegal_instruction_fault(this->fault_data); - auto it = csr_rd_cb.find(addr); - if (it == csr_rd_cb.end() || !it->second) // non existent register - throw illegal_instruction_fault(this->fault_data); - return (this->*(it->second))(addr, val); -} - -template iss::status riscv_hart_m_p::write_csr(unsigned addr, reg_t val) { - if (addr >= csr.size()) return iss::Err; - auto req_priv_lvl = (addr >> 8) & 0x3; - if (this->reg.PRIV < req_priv_lvl) // not having required privileges - throw illegal_instruction_fault(this->fault_data); - if((addr&0xc00)==0xc00) // writing to read-only region - throw illegal_instruction_fault(this->fault_data); - auto it = csr_wr_cb.find(addr); - if (it == csr_wr_cb.end() || !it->second) // non existent register - throw illegal_instruction_fault(this->fault_data); - return (this->*(it->second))(addr, val); -} - -template iss::status riscv_hart_m_p::read_csr_reg(unsigned addr, reg_t &val) { - val = csr[addr]; - return iss::Ok; -} - -template iss::status riscv_hart_m_p::read_null(unsigned addr, reg_t &val) { - val = 0; - return iss::Ok; -} - -template iss::status riscv_hart_m_p::write_csr_reg(unsigned addr, reg_t val) { - csr[addr] = val; - return iss::Ok; -} - -template iss::status riscv_hart_m_p::read_cycle(unsigned addr, reg_t &val) { - auto cycle_val = this->reg.icount + cycle_offset; - if (addr == mcycle) { - val = static_cast(cycle_val); - } else if (addr == mcycleh) { - if (sizeof(typename traits::reg_t) != 4) return iss::Err; - val = static_cast(cycle_val >> 32); - } - return iss::Ok; -} - -template iss::status riscv_hart_m_p::write_cycle(unsigned addr, reg_t val) { - if (sizeof(typename traits::reg_t) != 4) { - if (addr == mcycleh) - return iss::Err; - mcycle_csr = static_cast(val); - } else { - if (addr == mcycle) { - mcycle_csr = (mcycle_csr & 0xffffffff00000000) + val; - } else { - mcycle_csr = (static_cast(val)<<32) + (mcycle_csr & 0xffffffff); - } - } - cycle_offset = mcycle_csr-this->reg.icount; // TODO: relying on wrap-around - return iss::Ok; -} - -template iss::status riscv_hart_m_p::read_instret(unsigned addr, reg_t &val) { - if ((addr&0xff) == (minstret&0xff)) { - val = static_cast(this->reg.instret); - } else if ((addr&0xff) == (minstreth&0xff)) { - if (sizeof(typename traits::reg_t) != 4) return iss::Err; - val = static_cast(this->reg.instret >> 32); - } - return iss::Ok; -} - -template iss::status riscv_hart_m_p::write_instret(unsigned addr, reg_t val) { - if (sizeof(typename traits::reg_t) != 4) { - if ((addr&0xff) == (minstreth&0xff)) - return iss::Err; - this->reg.instret = static_cast(val); - } else { - if ((addr&0xff) == (minstret&0xff)) { - this->reg.instret = (this->reg.instret & 0xffffffff00000000) + val; - } else { - this->reg.instret = (static_cast(val)<<32) + (this->reg.instret & 0xffffffff); - } - } - this->reg.instret--; - return iss::Ok; -} - -template iss::status riscv_hart_m_p::read_time(unsigned addr, reg_t &val) { - uint64_t time_val = this->reg.icount / (100000000 / 32768 - 1); //-> ~3052; - if (addr == time) { - val = static_cast(time_val); - } else if (addr == timeh) { - if (sizeof(typename traits::reg_t) != 4) return iss::Err; - val = static_cast(time_val >> 32); - } - return iss::Ok; -} - -template iss::status riscv_hart_m_p::read_tvec(unsigned addr, reg_t &val) { - val = csr[mtvec] & ~2; - return iss::Ok; -} - -template iss::status riscv_hart_m_p::read_status(unsigned addr, reg_t &val) { - val = state.mstatus & hart_state_type::get_mask(); - return iss::Ok; -} - -template iss::status riscv_hart_m_p::write_status(unsigned addr, reg_t val) { - state.write_mstatus(val); - check_interrupt(); - return iss::Ok; -} - -template iss::status riscv_hart_m_p::write_cause(unsigned addr, reg_t val) { - csr[mcause] = val & ((1UL<<(traits::XLEN-1))| (mcause_max_irq-1)); - return iss::Ok; -} - -template iss::status riscv_hart_m_p::read_hartid(unsigned addr, reg_t &val) { - val = mhartid_reg; - return iss::Ok; -} - -template iss::status riscv_hart_m_p::read_ie(unsigned addr, reg_t &val) { - auto mask = get_irq_mask(); - val = csr[mie] & mask; - return iss::Ok; -} - -template iss::status riscv_hart_m_p::write_ie(unsigned addr, reg_t val) { - auto mask = get_irq_mask(); - csr[mie] = (csr[mie] & ~mask) | (val & mask); - check_interrupt(); - return iss::Ok; -} - -template iss::status riscv_hart_m_p::read_ip(unsigned addr, reg_t &val) { - auto mask = get_irq_mask(); - val = csr[mip] & mask; - return iss::Ok; -} - -template iss::status riscv_hart_m_p::write_epc(unsigned addr, reg_t val) { - csr[addr] = val & get_pc_mask(); - return iss::Ok; -} - -template iss::status riscv_hart_m_p::write_dcsr_dcsr(unsigned addr, reg_t val) { - if(!debug_mode_active()) - throw illegal_instruction_fault(this->fault_data); - // +-------------- ebreakm - // | +---------- stepi - // | | +++----- cause - // | | ||| +- step - csr[addr] = val & 0b1000100111000100U; - return iss::Ok; -} - -template iss::status riscv_hart_m_p::read_dcsr_reg(unsigned addr, reg_t &val) { - if(!debug_mode_active()) - throw illegal_instruction_fault(this->fault_data); - val = csr[addr]; - return iss::Ok; -} - -template iss::status riscv_hart_m_p::write_dcsr_reg(unsigned addr, reg_t val) { - if(!debug_mode_active()) - throw illegal_instruction_fault(this->fault_data); - csr[addr] = val; - return iss::Ok; -} - -template iss::status riscv_hart_m_p::read_dpc_reg(unsigned addr, reg_t &val) { - if(!debug_mode_active()) - throw illegal_instruction_fault(this->fault_data); - val = this->reg.DPC; - return iss::Ok; -} - -template iss::status riscv_hart_m_p::write_dpc_reg(unsigned addr, reg_t val) { - if(!debug_mode_active()) - throw illegal_instruction_fault(this->fault_data); - this->reg.DPC = val; - return iss::Ok; -} - -template -iss::status riscv_hart_m_p::write_intthresh(unsigned addr, reg_t val) { - csr[addr]= val &0xff; - return iss::Ok; -} - -template -iss::status riscv_hart_m_p::read_mem(phys_addr_t paddr, unsigned length, uint8_t *const data) { - if(mem_read_cb) return mem_read_cb(paddr, length, data); - switch (paddr.val) { - case 0x0200BFF8: { // CLINT base, mtime reg - if (sizeof(reg_t) < length) return iss::Err; - reg_t time_val; - this->read_csr(time, time_val); - std::copy((uint8_t *)&time_val, ((uint8_t *)&time_val) + length, data); - } break; - case 0x10008000: { - const mem_type::page_type &p = mem(paddr.val / mem.page_size); - uint64_t offs = paddr.val & mem.page_addr_mask; - std::copy(p.data() + offs, p.data() + offs + length, data); - if (this->reg.icount > 30000) data[3] |= 0x80; - } break; - default: { - for(auto offs=0U; offs -iss::status riscv_hart_m_p::write_mem(phys_addr_t paddr, unsigned length, const uint8_t *const data) { - if(mem_write_cb) return mem_write_cb(paddr, length, data); - switch (paddr.val) { - case 0x10013000: // UART0 base, TXFIFO reg - case 0x10023000: // UART1 base, TXFIFO reg - uart_buf << (char)data[0]; - if (((char)data[0]) == '\n' || data[0] == 0) { - // LOG(INFO)<<"UART"<<((paddr.val>>16)&0x3)<<" send - // '"<::XLEN == 32 && paddr.val == (tohost + 4)) || - (traits::XLEN == 64 && paddr.val == tohost); - auto tohost_lower = - (traits::XLEN == 32 && paddr.val == tohost) || (traits::XLEN == 64 && paddr.val == tohost); - if (tohost_lower || tohost_upper) { - uint64_t hostvar = *reinterpret_cast(p.data() + (tohost & mem.page_addr_mask)); - if (tohost_upper || (tohost_lower && to_host_wr_cnt > 0)) { - switch (hostvar >> 48) { - case 0: - if (hostvar != 0x1) { - LOG(FATAL) << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar - << "), stopping simulation"; - } else { - LOG(INFO) << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar - << "), stopping simulation"; - } - this->reg.trap_state=std::numeric_limits::max(); - this->interrupt_sim=hostvar; - break; - //throw(iss::simulation_stopped(hostvar)); - case 0x0101: { - char c = static_cast(hostvar & 0xff); - if (c == '\n' || c == 0) { - LOG(INFO) << "tohost send '" << uart_buf.str() << "'"; - uart_buf.str(""); - } else - uart_buf << c; - to_host_wr_cnt = 0; - } break; - default: - break; - } - } else if (tohost_lower) - to_host_wr_cnt++; - } else if ((traits::XLEN == 32 && paddr.val == fromhost + 4) || - (traits::XLEN == 64 && paddr.val == fromhost)) { - uint64_t fhostvar = *reinterpret_cast(p.data() + (fromhost & mem.page_addr_mask)); - *reinterpret_cast(p.data() + (tohost & mem.page_addr_mask)) = fhostvar; - } - } - } - } - return iss::Ok; -} - -template -iss::status riscv_hart_m_p::read_clic(uint64_t addr, unsigned length, uint8_t *const data) { - if(addr==clic_base_addr) { // cliccfg - *data=clic_cfg_reg; - for(auto i=1; i=(clic_base_addr+4) && (addr+length)<=(clic_base_addr+8)){ // clicinfo - read_reg_uint32(addr, clic_info_reg, data, length); - } else if(addr>=(clic_base_addr+0x40) && (addr+length)<=(clic_base_addr+0x40+clic_num_trigger*4)){ // clicinttrig - auto offset = ((addr&0x7fff)-0x40)/4; - read_reg_uint32(addr, clic_inttrig_reg[offset], data, length); - } else if(addr>=(clic_base_addr+0x1000) && (addr+length)<=(clic_base_addr+clic_num_irq*4)){ // clicintip/clicintie/clicintattr/clicintctl - auto offset = ((addr&0x7fff)-0x1000)/4; - read_reg_uint32(addr, clic_int_reg[offset].raw, data, length); - } else { - for(auto i = 0U; i -iss::status riscv_hart_m_p::write_clic(uint64_t addr, unsigned length, const uint8_t *const data) { - if(addr==clic_base_addr) { // cliccfg - clic_cfg_reg = *data; - clic_cfg_reg&= 0x7e; -// } else if(addr>=(clic_base_addr+4) && (addr+length)<=(clic_base_addr+4)){ // clicinfo -// write_uint32(addr, clic_info_reg, data, length); - } else if(addr>=(clic_base_addr+0x40) && (addr+length)<=(clic_base_addr+0xC0)){ // clicinttrig - auto offset = ((addr&0x7fff)-0x40)/4; - write_reg_uint32(addr, clic_inttrig_reg[offset], data, length); - } else if(addr>=(clic_base_addr+0x1000) && (addr+length)<=(clic_base_addr+clic_num_irq*4)){ // clicintip/clicintie/clicintattr/clicintctl - auto offset = ((addr&0x7fff)-0x1000)/4; - write_reg_uint32(addr, clic_int_reg[offset].raw, data, length); - } - return iss::Ok; -} - -template inline void riscv_hart_m_p::reset(uint64_t address) { - BASE::reset(address); - state.mstatus = hart_state_type::mstatus_reset_val; -} - -template void riscv_hart_m_p::check_interrupt() { - //auto ideleg = csr[mideleg]; - // Multiple simultaneous interrupts and traps at the same privilege level are - // handled in the following decreasing priority order: - // external interrupts, software interrupts, timer interrupts, then finally - // any synchronous traps. - auto ena_irq = csr[mip] & csr[mie]; - - bool mie = state.mstatus.MIE; - auto m_enabled = this->reg.PRIV < PRIV_M || (this->reg.PRIV == PRIV_M && mie); - auto enabled_interrupts = m_enabled ? ena_irq : 0; - - if (enabled_interrupts != 0) { - int res = 0; - while ((enabled_interrupts & 1) == 0) { - enabled_interrupts >>= 1; - res++; - } - this->reg.pending_trap = res << 16 | 1; // 0x80 << 24 | (cause << 16) | trap_id - } -} - -template uint64_t riscv_hart_m_p::enter_trap(uint64_t flags, uint64_t addr, uint64_t instr) { - // flags are ACTIVE[31:31], CAUSE[30:16], TRAPID[15:0] - // calculate and write mcause val - auto trap_id = bit_sub<0, 16>(flags); - auto cause = bit_sub<16, 15>(flags); - // calculate effective privilege level - unsigned new_priv = PRIV_M; - if (trap_id == 0) { // exception - if (cause == 11) cause = 0x8 + PRIV_M; // adjust environment call cause - // store ret addr in xepc register - csr[mepc] = static_cast(addr) & get_pc_mask(); // store actual address instruction of exception - /* - * write mtval if new_priv=M_MODE, spec says: - * When a hardware breakpoint is triggered, or an instruction-fetch, load, - * or store address-misaligned, - * access, or page-fault exception occurs, mtval is written with the - * faulting effective address. - */ - switch(cause){ - case 0: - csr[mtval] = static_cast(addr); - break; - case 2: - csr[mtval] = (instr & 0x3)==3?instr:instr&0xffff; - break; - case 3: - if((FEAT & FEAT_DEBUG) && (csr[dcsr] & 0x8000)) { - this->reg.DPC = addr; - csr[dcsr] = (csr[dcsr] & ~0x1c3) | (1<<6) | PRIV_M; //FIXME: cause should not be 4 (stepi) - new_priv = this->reg.PRIV | PRIV_D; - } else { - csr[mtval] = addr; - } - break; - case 4: - case 6: - csr[mtval] = fault_data; - break; - default: - csr[mtval] = 0; - } - fault_data = 0; - } else { - csr[mepc] = this->reg.NEXT_PC & get_pc_mask(); // store next address if interrupt - this->reg.pending_trap = 0; - } - csr[mcause] = (trap_id << (traits::XLEN-1)) + cause; - // update mstatus - // xPP field of mstatus is written with the active privilege mode at the time - // of the trap; the x PIE field of mstatus - // is written with the value of the active interrupt-enable bit at the time of - // the trap; and the x IE field of mstatus - // is cleared - // store the actual privilege level in yPP and store interrupt enable flags - state.mstatus.MPP = PRIV_M; - state.mstatus.MPIE = state.mstatus.MIE; - state.mstatus.MIE = false; - - // get trap vector - auto ivec = csr[mtvec]; - // calculate addr// set NEXT_PC to trap addressess to jump to based on MODE - // bits in mtvec - this->reg.NEXT_PC = ivec & ~0x3UL; - if ((ivec & 0x1) == 1 && trap_id != 0) this->reg.NEXT_PC += 4 * cause; - // reset trap state - this->reg.PRIV = new_priv; - this->reg.trap_state = 0; - std::array buffer; -#if defined(_MSC_VER) - sprintf(buffer.data(), "0x%016llx", addr); -#else - sprintf(buffer.data(), "0x%016lx", addr); -#endif - if((flags&0xffffffff) != 0xffffffff) - CLOG(INFO, disass) << (trap_id ? "Interrupt" : "Trap") << " with cause '" - << (trap_id ? irq_str[cause] : trap_str[cause]) << "' (" << cause << ")" - << " at address " << buffer.data() << " occurred"; - return this->reg.NEXT_PC; -} - -template uint64_t riscv_hart_m_p::leave_trap(uint64_t flags) { - state.mstatus.MIE = state.mstatus.MPIE; - state.mstatus.MPIE = 1; - // sets the pc to the value stored in the x epc register. - this->reg.NEXT_PC = csr[mepc] & get_pc_mask(); - CLOG(INFO, disass) << "Executing xRET"; - check_interrupt(); - return this->reg.NEXT_PC; -} - -} // namespace arch -} // namespace iss - -#endif /* _RISCV_HART_M_P_H */ diff --git a/incl/iss/arch/riscv_hart_mu_p.h b/incl/iss/arch/riscv_hart_mu_p.h deleted file mode 100644 index bd50342..0000000 --- a/incl/iss/arch/riscv_hart_mu_p.h +++ /dev/null @@ -1,1421 +0,0 @@ -/******************************************************************************* - * Copyright (C) 2021 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 implementation - ******************************************************************************/ - -#ifndef _RISCV_HART_MU_P_H -#define _RISCV_HART_MU_P_H - -#include "riscv_hart_common.h" -#include "iss/arch/traits.h" -#include "iss/instrumentation_if.h" -#include "iss/log_categories.h" -#include "iss/vm_if.h" -#ifndef FMT_HEADER_ONLY -#define FMT_HEADER_ONLY -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if defined(__GNUC__) -#define likely(x) __builtin_expect(!!(x), 1) -#define unlikely(x) __builtin_expect(!!(x), 0) -#else -#define likely(x) x -#define unlikely(x) x -#endif - -namespace iss { -namespace arch { - -template class riscv_hart_mu_p : public BASE { -protected: - const std::array lvl = {{'U', 'S', 'H', 'M'}}; - const std::array trap_str = {{"" - "Instruction address misaligned", // 0 - "Instruction access fault", // 1 - "Illegal instruction", // 2 - "Breakpoint", // 3 - "Load address misaligned", // 4 - "Load access fault", // 5 - "Store/AMO address misaligned", // 6 - "Store/AMO access fault", // 7 - "Environment call from U-mode", // 8 - "Environment call from S-mode", // 9 - "Reserved", // a - "Environment call from M-mode", // b - "Instruction page fault", // c - "Load page fault", // d - "Reserved", // e - "Store/AMO page fault"}}; - const std::array irq_str = { - {"User software interrupt", "Supervisor software interrupt", "Reserved", "Machine software interrupt", - "User timer interrupt", "Supervisor timer interrupt", "Reserved", "Machine timer interrupt", - "User external interrupt", "Supervisor external interrupt", "Reserved", "Machine external interrupt"}}; -public: - using core = BASE; - using this_class = riscv_hart_mu_p; - using phys_addr_t = typename core::phys_addr_t; - using reg_t = typename core::reg_t; - using addr_t = typename core::addr_t; - - using rd_csr_f = iss::status (this_class::*)(unsigned addr, reg_t &); - using wr_csr_f = iss::status (this_class::*)(unsigned addr, reg_t); - using mem_read_f = iss::status(phys_addr_t addr, unsigned, uint8_t *const); - using mem_write_f = iss::status(phys_addr_t addr, unsigned, uint8_t const *const); - - // primary template - template struct hart_state {}; - // specialization 32bit - template class hart_state::value>::type> { - public: - BEGIN_BF_DECL(mstatus_t, T); - // SD bit is read-only and is set when either the FS or XS bits encode a Dirty state (i.e., SD=((FS==11) OR XS==11))) - BF_FIELD(SD, 31, 1); - // Trap SRET - BF_FIELD(TSR, 22, 1); - // Timeout Wait - BF_FIELD(TW, 21, 1); - // Trap Virtual Memory - BF_FIELD(TVM, 20, 1); - // Make eXecutable Readable - BF_FIELD(MXR, 19, 1); - // permit Supervisor User Memory access - BF_FIELD(SUM, 18, 1); - // Modify PRiVilege - BF_FIELD(MPRV, 17, 1); - // status of additional user-mode extensions and associated state, All off/None dirty or clean, some on/None dirty, some clean/Some dirty - BF_FIELD(XS, 15, 2); - // floating-point unit status Off/Initial/Clean/Dirty - BF_FIELD(FS, 13, 2); - // machine previous privilege - BF_FIELD(MPP, 11, 2); - // supervisor previous privilege - BF_FIELD(SPP, 8, 1); - // previous machine interrupt-enable - BF_FIELD(MPIE, 7, 1); - // previous supervisor interrupt-enable - BF_FIELD(SPIE, 5, 1); - // previous user interrupt-enable - BF_FIELD(UPIE, 4, 1); - // machine interrupt-enable - BF_FIELD(MIE, 3, 1); - // supervisor interrupt-enable - BF_FIELD(SIE, 1, 1); - // user interrupt-enable - BF_FIELD(UIE, 0, 1); - END_BF_DECL(); - - mstatus_t mstatus; - - static const reg_t mstatus_reset_val = 0x1800; // MPP set to 1 - - void write_mstatus(T val, unsigned priv_lvl) { - auto mask = get_mask(priv_lvl); - auto new_val = (mstatus.backing.val & ~mask) | (val & mask); - mstatus = new_val; - } - - static constexpr uint32_t get_mask(unsigned priv_lvl) { -#if __cplusplus < 201402L - return priv_lvl == PRIV_U ? 0x80000011UL : priv_lvl == PRIV_S ? 0x800de133UL : 0x807ff9ddUL; -#else - switch (priv_lvl) { - case PRIV_U: return 0x00000011UL; // 0b1000 0000 0000 0000 0000 0000 0001 0001 - default: - // +-SD - // | +-TSR - // | |+-TW - // | ||+-TVM - // | |||+-MXR - // | ||||+-SUM - // | |||||+-MPRV - // | |||||| +-XS - // | |||||| | +-FS - // | |||||| | | +-MPP - // | |||||| | | | +-SPP - // | |||||| | | | |+-MPIE - // | |||||| | | | || +-UPIE - // | ||||||/|/|/| || |+-MIE - // | ||||||/|/|/| || || +-UIE - return 0b00000000000000000001100010011001; - } -#endif - } - }; - using hart_state_type = hart_state; - - constexpr reg_t get_irq_mask(size_t mode) { - std::array m = {{ - 0b000100010001, // U mode - 0b001100110011, // S mode - 0, - 0b100110011001 // M mode - }}; - return m[mode]; - } - - constexpr reg_t get_pc_mask() { - return traits::MISA_VAL&0b0100?~1:~3; - } - - riscv_hart_mu_p(feature_config cfg = feature_config{}); - virtual ~riscv_hart_mu_p() = default; - - void reset(uint64_t address) override; - - std::pair load_file(std::string name, int type = -1) override; - - iss::status read(const address_type type, const access_type access, const uint32_t space, - const uint64_t addr, const unsigned length, uint8_t *const data) override; - iss::status write(const address_type type, const access_type access, const uint32_t space, - const uint64_t addr, const unsigned length, const uint8_t *const data) override; - - uint64_t enter_trap(uint64_t flags) override { return riscv_hart_mu_p::enter_trap(flags, fault_data, fault_data); } - uint64_t enter_trap(uint64_t flags, uint64_t addr, uint64_t instr) override; - uint64_t leave_trap(uint64_t flags) override; - - const reg_t& get_mhartid() const { return mhartid_reg; } - void set_mhartid(reg_t mhartid) { mhartid_reg = mhartid; }; - - void disass_output(uint64_t pc, const std::string instr) override { - CLOG(INFO, disass) << fmt::format("0x{:016x} {:40} [p:{};s:0x{:x};c:{}]", - pc, instr, lvl[this->reg.PRIV], (reg_t)state.mstatus, this->reg.icount + cycle_offset); - }; - - iss::instrumentation_if *get_instrumentation_if() override { return &instr_if; } - - void setMemReadCb(std::function const& memReadCb) { - mem_read_cb = memReadCb; - } - - void setMemWriteCb(std::function const& memWriteCb) { - mem_write_cb = memWriteCb; - } - - void set_csr(unsigned addr, reg_t val){ - csr[addr & csr.page_addr_mask] = val; - } - - void set_irq_num(unsigned i) { - mcause_max_irq=1< &arch) - : arch(arch) {} - /** - * get the name of this architecture - * - * @return the name of this architecture - */ - const std::string core_type_name() const override { return traits::core_type; } - - virtual uint64_t get_pc() { return arch.get_pc(); }; - - virtual uint64_t get_next_pc() { return arch.get_next_pc(); }; - - uint64_t get_instr_count() { return arch.reg.icount; } - - uint64_t get_total_cycles() override { return arch.reg.icount + arch.cycle_offset; } - - virtual void set_curr_instr_cycles(unsigned cycles) { arch.cycle_offset += cycles - 1; }; - - riscv_hart_mu_p &arch; - }; - - friend struct riscv_instrumentation_if; - addr_t get_pc() { return this->reg.PC; } - addr_t get_next_pc() { return this->reg.NEXT_PC; } - - virtual iss::status read_mem(phys_addr_t addr, unsigned length, uint8_t *const data); - virtual iss::status write_mem(phys_addr_t addr, unsigned length, const uint8_t *const data); - - iss::status read_clic(uint64_t addr, unsigned length, uint8_t *const data); - iss::status write_clic(uint64_t addr, unsigned length, const uint8_t *const data); - - virtual iss::status read_csr(unsigned addr, reg_t &val); - virtual iss::status write_csr(unsigned addr, reg_t val); - - hart_state_type state; - int64_t cycle_offset{0}; - uint64_t mcycle_csr{0}; - int64_t instret_offset{0}; - uint64_t minstret_csr{0}; - reg_t fault_data; - uint64_t tohost = tohost_dflt; - uint64_t fromhost = fromhost_dflt; - unsigned to_host_wr_cnt = 0; - riscv_instrumentation_if instr_if; - - using mem_type = util::sparse_array; - using csr_type = util::sparse_array::reg_t, 1ULL << 12, 12>; - using csr_page_type = typename csr_type::page_type; - mem_type mem; - csr_type csr; - std::stringstream uart_buf; - std::unordered_map ptw; - std::unordered_map atomic_reservation; - std::unordered_map csr_rd_cb; - std::unordered_map csr_wr_cb; - uint8_t clic_cfg_reg{0}; - uint32_t clic_info_reg{0}; - std::array clic_inttrig_reg; - union clic_int_reg_t { - struct{ - uint8_t ip; - uint8_t ie; - uint8_t attr; - uint8_t ctl; - }; - uint32_t raw; - }; - std::vector clic_int_reg; - - std::vector tcm; - - iss::status read_csr_reg(unsigned addr, reg_t &val); - iss::status write_csr_reg(unsigned addr, reg_t val); - iss::status read_null(unsigned addr, reg_t &val); - iss::status write_null(unsigned addr, reg_t val){return iss::status::Ok;} - iss::status read_cycle(unsigned addr, reg_t &val); - iss::status write_cycle(unsigned addr, reg_t val); - iss::status read_instret(unsigned addr, reg_t &val); - iss::status write_instret(unsigned addr, reg_t val); - iss::status read_tvec(unsigned addr, reg_t &val); - iss::status read_time(unsigned addr, reg_t &val); - iss::status read_status(unsigned addr, reg_t &val); - iss::status write_status(unsigned addr, reg_t val); - iss::status write_cause(unsigned addr, reg_t val); - iss::status read_ie(unsigned addr, reg_t &val); - iss::status write_ie(unsigned addr, reg_t val); - iss::status read_ip(unsigned addr, reg_t &val); - iss::status write_ideleg(unsigned addr, reg_t val); - iss::status write_edeleg(unsigned addr, reg_t val); - iss::status read_hartid(unsigned addr, reg_t &val); - iss::status write_epc(unsigned addr, reg_t val); - iss::status write_intstatus(unsigned addr, reg_t val); - iss::status write_intthresh(unsigned addr, reg_t val); - iss::status write_dcsr_dcsr(unsigned addr, reg_t val); - iss::status read_dcsr_reg(unsigned addr, reg_t &val); - iss::status write_dcsr_reg(unsigned addr, reg_t val); - iss::status read_dpc_reg(unsigned addr, reg_t &val); - iss::status write_dpc_reg(unsigned addr, reg_t val); - iss::status write_pmpcfg_reg(unsigned addr, reg_t val); - - virtual iss::status read_custom_csr_reg(unsigned addr, reg_t &val) {return iss::status::Err;}; - virtual iss::status write_custom_csr_reg(unsigned addr, reg_t val) {return iss::status::Err;}; - - void register_custom_csr_rd(unsigned addr){ - csr_rd_cb[addr] = &this_class::read_custom_csr_reg; - } - void register_custom_csr_wr(unsigned addr){ - csr_wr_cb[addr] = &this_class::write_custom_csr_reg; - } - - reg_t mhartid_reg{0x0}; - std::functionmem_read_cb; - std::function mem_write_cb; - - void check_interrupt(); - bool pmp_check(const access_type type, const uint64_t addr, const unsigned len); - std::vector> memfn_range; - std::vector> memfn_read; - std::vector> memfn_write; - void insert_mem_range(uint64_t, uint64_t, std::function, std::function); - feature_config cfg; - unsigned mcause_max_irq{16}; - inline bool debug_mode_active() {return this->reg.PRIV&0x4;} -}; - -template -riscv_hart_mu_p::riscv_hart_mu_p(feature_config cfg) -: state() -, instr_if(*this) -, cfg(cfg) { - // reset values - csr[misa] = traits::MISA_VAL; - csr[mvendorid] = 0x669; - csr[marchid] = traits::MARCHID_VAL; - csr[mimpid] = 1; - csr[mclicbase] = cfg.clic_base; // TODO: should be taken from YAML file - - uart_buf.str(""); - for (unsigned addr = mhpmcounter3; addr <= mhpmcounter31; ++addr){ - csr_rd_cb[addr] = &this_class::read_null; - csr_wr_cb[addr] = &this_class::write_csr_reg; - } - for (unsigned addr = mhpmcounter3h; addr <= mhpmcounter31h; ++addr){ - csr_rd_cb[addr] = &this_class::read_null; - csr_wr_cb[addr] = &this_class::write_csr_reg; - } - for (unsigned addr = mhpmevent3; addr <= mhpmevent31; ++addr){ - csr_rd_cb[addr] = &this_class::read_null; - csr_wr_cb[addr] = &this_class::write_csr_reg; - } - for (unsigned addr = hpmcounter3; addr <= hpmcounter31; ++addr){ - csr_rd_cb[addr] = &this_class::read_null; - } - for (unsigned addr = hpmcounter3h; addr <= hpmcounter31h; ++addr){ - csr_rd_cb[addr] = &this_class::read_null; - //csr_wr_cb[addr] = &this_class::write_csr_reg; - } - // common regs - const std::array addrs{{ - misa, mvendorid, marchid, mimpid, - mepc, mtvec, mscratch, mcause, mtval, - uepc, utvec, uscratch, ucause, utval, - }}; - for(auto addr: addrs) { - csr_rd_cb[addr] = &this_class::read_csr_reg; - csr_wr_cb[addr] = &this_class::write_csr_reg; - } - // special handling & overrides - csr_rd_cb[time] = &this_class::read_time; - csr_rd_cb[timeh] = &this_class::read_time; - csr_rd_cb[cycle] = &this_class::read_cycle; - csr_rd_cb[cycleh] = &this_class::read_cycle; - csr_rd_cb[instret] = &this_class::read_instret; - csr_rd_cb[instreth] = &this_class::read_instret; - - csr_rd_cb[mcycle] = &this_class::read_cycle; - csr_wr_cb[mcycle] = &this_class::write_cycle; - csr_rd_cb[mcycleh] = &this_class::read_cycle; - csr_wr_cb[mcycleh] = &this_class::write_cycle; - csr_rd_cb[minstret] = &this_class::read_instret; - csr_wr_cb[minstret] = &this_class::write_instret; - csr_rd_cb[minstreth] = &this_class::read_instret; - csr_wr_cb[minstreth] = &this_class::write_instret; - csr_rd_cb[mstatus] = &this_class::read_status; - csr_wr_cb[mstatus] = &this_class::write_status; - csr_wr_cb[mcause] = &this_class::write_cause; - csr_rd_cb[mtvec] = &this_class::read_tvec; - csr_wr_cb[mepc] = &this_class::write_epc; - csr_rd_cb[mip] = &this_class::read_ip; - csr_wr_cb[mip] = &this_class::write_null; - csr_rd_cb[mie] = &this_class::read_ie; - csr_wr_cb[mie] = &this_class::write_ie; - csr_rd_cb[mhartid] = &this_class::read_hartid; - csr_rd_cb[mcounteren] = &this_class::read_null; - csr_wr_cb[mcounteren] = &this_class::write_null; - csr_wr_cb[misa] = &this_class::write_null; - csr_wr_cb[mvendorid] = &this_class::write_null; - csr_wr_cb[marchid] = &this_class::write_null; - csr_wr_cb[mimpid] = &this_class::write_null; - - if(FEAT & FEAT_PMP){ - for(size_t i=pmpaddr0; i<=pmpaddr15; ++i){ - csr_rd_cb[i] = &this_class::read_csr_reg; - csr_wr_cb[i] = &this_class::write_csr_reg; - } - for(size_t i=pmpcfg0; i<=pmpcfg3; ++i){ - csr_rd_cb[i] = &this_class::read_csr_reg; - csr_wr_cb[i] = &this_class::write_pmpcfg_reg; - } - } - if(FEAT & FEAT_EXT_N){ - csr_rd_cb[mideleg] = &this_class::read_csr_reg; - csr_wr_cb[mideleg] = &this_class::write_ideleg; - csr_rd_cb[medeleg] = &this_class::read_csr_reg; - csr_wr_cb[medeleg] = &this_class::write_edeleg; - csr_rd_cb[uie] = &this_class::read_ie; - csr_wr_cb[uie] = &this_class::write_ie; - csr_rd_cb[uip] = &this_class::read_ip; - csr_wr_cb[uip] = &this_class::write_null; - csr_wr_cb[uepc] = &this_class::write_epc; - csr_rd_cb[ustatus] = &this_class::read_status; - csr_wr_cb[ustatus] = &this_class::write_status; - csr_wr_cb[ucause] = &this_class::write_cause; - csr_rd_cb[utvec] = &this_class::read_tvec; - } - if(FEAT & FEAT_CLIC) { - csr_rd_cb[mtvt] = &this_class::read_csr_reg; - csr_wr_cb[mtvt] = &this_class::write_csr_reg; - csr_rd_cb[mxnti] = &this_class::read_csr_reg; - csr_wr_cb[mxnti] = &this_class::write_csr_reg; - csr_rd_cb[mintstatus] = &this_class::read_csr_reg; - csr_wr_cb[mintstatus] = &this_class::write_null; - csr_rd_cb[mscratchcsw] = &this_class::read_csr_reg; - csr_wr_cb[mscratchcsw] = &this_class::write_csr_reg; - csr_rd_cb[mscratchcswl] = &this_class::read_csr_reg; - csr_wr_cb[mscratchcswl] = &this_class::write_csr_reg; - csr_rd_cb[mintthresh] = &this_class::read_csr_reg; - csr_wr_cb[mintthresh] = &this_class::write_intthresh; - csr_rd_cb[mclicbase] = &this_class::read_csr_reg; - csr_wr_cb[mclicbase] = &this_class::write_null; - - clic_int_reg.resize(cfg.clic_num_irq); - clic_cfg_reg=0x20; - clic_info_reg = (/*CLICINTCTLBITS*/ 4U<<21) + cfg.clic_num_irq; - mcause_max_irq=cfg.clic_num_irq+16; - insert_mem_range(cfg.clic_base, 0x5000UL, - [this](phys_addr_t addr, unsigned length, uint8_t * const data) { return read_clic(addr.val, length, data);}, - [this](phys_addr_t addr, unsigned length, uint8_t const * const data) {return write_clic(addr.val, length, data);}); - } - if(FEAT & FEAT_TCM) { - tcm.resize(cfg.tcm_size); - std::function read_clic_cb = [this](phys_addr_t addr, unsigned length, uint8_t * const data) { - auto offset=addr.val-this->cfg.tcm_base; - std::copy(tcm.data() + offset, tcm.data() + offset + length, data); - return iss::Ok; - }; - std::function write_clic_cb = [this](phys_addr_t addr, unsigned length, uint8_t const * const data) { - auto offset=addr.val-this->cfg.tcm_base; - std::copy(data, data + length, tcm.data() + offset); - return iss::Ok; - }; - insert_mem_range(cfg.tcm_base, cfg.tcm_size, read_clic_cb, write_clic_cb); - } - if(FEAT & FEAT_DEBUG){ - csr_wr_cb[dscratch0] = &this_class::write_dcsr_reg; - csr_rd_cb[dscratch0] = &this_class::read_dcsr_reg; - csr_wr_cb[dscratch1] = &this_class::write_dcsr_reg; - csr_rd_cb[dscratch1] = &this_class::read_dcsr_reg; - csr_wr_cb[dpc] = &this_class::write_dpc_reg; - csr_rd_cb[dpc] = &this_class::read_dpc_reg; - csr_wr_cb[dcsr] = &this_class::write_dcsr_dcsr; - csr_rd_cb[dcsr] = &this_class::read_dcsr_reg; - } -} - -template std::pair riscv_hart_mu_p::load_file(std::string name, int type) { - FILE *fp = fopen(name.c_str(), "r"); - if (fp) { - std::array buf; - auto n = fread(buf.data(), 1, 4, fp); - if (n != 4) throw std::runtime_error("input file has insufficient size"); - buf[4] = 0; - if (strcmp(buf.data() + 1, "ELF") == 0) { - fclose(fp); - // Create elfio reader - ELFIO::elfio reader; - // Load ELF data - if (!reader.load(name)) throw std::runtime_error("could not process elf file"); - // check elf properties - if (reader.get_class() != ELFCLASS32) - if (sizeof(reg_t) == 4) throw std::runtime_error("wrong elf class in file"); - if (reader.get_type() != ET_EXEC) throw std::runtime_error("wrong elf type in file"); - if (reader.get_machine() != EM_RISCV) throw std::runtime_error("wrong elf machine in file"); - auto entry = reader.get_entry(); - for (const auto pseg : reader.segments) { - const auto fsize = pseg->get_file_size(); // 0x42c/0x0 - const auto seg_data = pseg->get_data(); - if (fsize > 0) { - auto res = this->write(iss::address_type::PHYSICAL, iss::access_type::DEBUG_WRITE, - traits::MEM, pseg->get_physical_address(), - fsize, reinterpret_cast(seg_data)); - if (res != iss::Ok) - LOG(ERR) << "problem writing " << fsize << "bytes to 0x" << std::hex - << pseg->get_physical_address(); - } - } - for(const auto sec : reader.sections) { - if(sec->get_name() == ".symtab") { - if ( SHT_SYMTAB == sec->get_type() || - SHT_DYNSYM == sec->get_type() ) { - ELFIO::symbol_section_accessor symbols( reader, sec ); - auto sym_no = symbols.get_symbols_num(); - std::string name; - ELFIO::Elf64_Addr value = 0; - ELFIO::Elf_Xword size = 0; - unsigned char bind = 0; - unsigned char type = 0; - ELFIO::Elf_Half section = 0; - unsigned char other = 0; - for ( auto i = 0U; i < sym_no; ++i ) { - symbols.get_symbol( i, name, value, size, bind, type, section, other ); - if(name=="tohost") { - tohost = value; - } else if(name=="fromhost") { - fromhost = value; - } - } - } - } else if (sec->get_name() == ".tohost") { - tohost = sec->get_address(); - fromhost = tohost + 0x40; - } - - } - return std::make_pair(entry, true); - } - throw std::runtime_error("memory load file is not a valid elf file"); - } - throw std::runtime_error("memory load file not found"); -} - -template -inline void riscv_hart_mu_p::insert_mem_range(uint64_t base, uint64_t size, std::function rd_f, - std::function wr_fn) { - std::tuple entry{base, size}; - auto it = std::upper_bound( memfn_range.begin(), memfn_range.end(), entry, - [](std::tuple const& a, std::tuple const& b){ - return std::get<0>(a)(b); - }); - auto idx = std::distance(memfn_range.begin(), it); - memfn_range.insert(it, entry); - memfn_read.insert(std::begin(memfn_read)+idx, rd_f); - memfn_write.insert(std::begin(memfn_write)+idx, wr_fn); -} - -template -inline iss::status riscv_hart_mu_p::write_pmpcfg_reg(unsigned addr, reg_t val) { - csr[addr] = val & 0x9f9f9f9f; - return iss::Ok; -} - -template bool riscv_hart_mu_p::pmp_check(const access_type type, const uint64_t addr, const unsigned len) { - constexpr auto PMP_SHIFT=2U; - constexpr auto PMP_R = 0x1U; - constexpr auto PMP_W = 0x2U; - constexpr auto PMP_X = 0x4U; - constexpr auto PMP_A = 0x18U; - constexpr auto PMP_L = 0x80U; - constexpr auto PMP_TOR =0x1U; - constexpr auto PMP_NA4 =0x2U; - constexpr auto PMP_NAPOT =0x3U; - reg_t base = 0; - auto any_active = false; - for (size_t i = 0; i < 16; i++) { - reg_t tor = csr[pmpaddr0+i] << PMP_SHIFT; - uint8_t cfg = csr[pmpcfg0+(i/4)]>>(i%4); - if (cfg & PMP_A) { - any_active=true; - auto pmp_a = (cfg & PMP_A) >> 3; - auto is_tor = pmp_a == PMP_TOR; - auto is_na4 = pmp_a == PMP_NA4; - - reg_t mask = (csr[pmpaddr0+i] << 1) | (!is_na4); - mask = ~(mask & ~(mask + 1)) << PMP_SHIFT; - - // Check each 4-byte sector of the access - auto any_match = false; - auto all_match = true; - for (reg_t offset = 0; offset < len; offset += 1 << PMP_SHIFT) { - reg_t cur_addr = addr + offset; - auto napot_match = ((cur_addr ^ tor) & mask) == 0; - auto tor_match = base <= (cur_addr+len-1) && cur_addr < tor; - auto match = is_tor ? tor_match : napot_match; - any_match |= match; - all_match &= match; - } - if (any_match) { - // If the PMP matches only a strict subset of the access, fail it - if (!all_match) - return false; - return (this->reg.PRIV == PRIV_M && !(cfg & PMP_L)) || - (type == access_type::READ && (cfg & PMP_R)) || - (type == access_type::WRITE && (cfg & PMP_W)) || - (type == access_type::FETCH && (cfg & PMP_X)); - } - } - base = tor; - } -// constexpr auto pmp_num_regs = 16; -// reg_t tor_base = 0; -// auto any_active = false; -// auto lower_addr = addr >>2; -// auto upper_addr = (addr+len-1)>>2; -// for (size_t i = 0; i < pmp_num_regs; i++) { -// uint8_t cfg = csr[pmpcfg0+(i/4)]>>(i%4); -// uint8_t cfg_next = i==(pmp_num_regs-1)? 0 : csr[pmpcfg0+((i+1)/4)]>>((i+1)%4); -// auto pmpaddr = csr[pmpaddr0+i]; -// if (cfg & PMP_A) { -// any_active=true; -// auto is_tor = bit_sub<3, 2>(cfg) == PMP_TOR; -// auto is_napot = bit_sub<4, 1>(cfg) && bit_sub<3, 2>(cfg_next)!= PMP_TOR; -// if(is_napot) { -// reg_t mask = bit_sub<3, 1>(cfg)?~( pmpaddr & ~(pmpaddr + 1)): 0x3fffffff; -// auto mpmpaddr = pmpaddr & mask; -// if((lower_addr&mask) == mpmpaddr && (upper_addr&mask)==mpmpaddr) -// return (this->reg.PRIV == PRIV_M && !(cfg & PMP_L)) || -// (type == access_type::READ && (cfg & PMP_R)) || -// (type == access_type::WRITE && (cfg & PMP_W)) || -// (type == access_type::FETCH && (cfg & PMP_X)); -// } else if(is_tor) { -// if(lower_addr>=tor_base && upper_addr<=pmpaddr) -// return (this->reg.PRIV == PRIV_M && !(cfg & PMP_L)) || -// (type == access_type::READ && (cfg & PMP_R)) || -// (type == access_type::WRITE && (cfg & PMP_W)) || -// (type == access_type::FETCH && (cfg & PMP_X)); -// } -// } -// tor_base = pmpaddr; -// } - return !any_active || this->reg.PRIV == PRIV_M; -} - - -template -iss::status riscv_hart_mu_p::read(const address_type type, const access_type access, const uint32_t space, - const uint64_t addr, const unsigned length, uint8_t *const data) { -#ifndef NDEBUG - if (access && iss::access_type::DEBUG) { - LOG(TRACEALL) << "debug read of " << length << " bytes @addr 0x" << std::hex << addr; - } else if(access && iss::access_type::FETCH){ - LOG(TRACEALL) << "fetch of " << length << " bytes @addr 0x" << std::hex << addr; - } else { - LOG(TRACE) << "read of " << length << " bytes @addr 0x" << std::hex << addr; - } -#endif - try { - switch (space) { - case traits::MEM: { - if(FEAT & FEAT_PMP){ - if(!pmp_check(access, addr, length) && (access&access_type::DEBUG) != access_type::DEBUG) { - fault_data = addr; - if (access && iss::access_type::DEBUG) throw trap_access(0, addr); - this->reg.trap_state = (1 << 31) | ((access==access_type::FETCH?1:5) << 16); // issue trap 1 - return iss::Err; - } - } - if (unlikely((access == iss::access_type::FETCH || access == iss::access_type::DEBUG_FETCH) && (addr & 0x1) == 1)) { - fault_data = addr; - if (access && iss::access_type::DEBUG) throw trap_access(0, addr); - this->reg.trap_state = (1 << 31); // issue trap 0 - return iss::Err; - } - try { - auto alignment = access == iss::access_type::FETCH? (traits::MISA_VAL&0x100? 2 : 4) : length; - if(alignment>1 && (addr&(alignment-1))){ - this->reg.trap_state = 1<<31 | 4<<16; - fault_data=addr; - return iss::Err; - } - auto phys_addr = type==iss::address_type::PHYSICAL?phys_addr_t{access, space, addr}:BASE::v2p(iss::addr_t{access, type, space, addr}); - auto res = iss::Err; - if(access != access_type::FETCH && memfn_range.size()){ - auto it = std::find_if(std::begin(memfn_range), std::end(memfn_range), [phys_addr](std::tuple const& a){ - return std::get<0>(a)<=phys_addr.val && (std::get<0>(a)+std::get<1>(a))>phys_addr.val; - }); - if(it!=std::end(memfn_range)) { - auto idx = std::distance(std::begin(memfn_range), it); - res = memfn_read[idx](phys_addr, length, data); - } else - res = read_mem( phys_addr, length, data); - } else { - res = read_mem( phys_addr, length, data); - } - if (unlikely(res != iss::Ok)){ - this->reg.trap_state = (1 << 31) | (5 << 16); // issue trap 5 (load access fault - fault_data=addr; - } - return res; - } catch (trap_access &ta) { - this->reg.trap_state = (1 << 31) | ta.id; - fault_data=ta.addr; - return iss::Err; - } - } break; - case traits::CSR: { - if (length != sizeof(reg_t)) return iss::Err; - return read_csr(addr, *reinterpret_cast(data)); - } break; - case traits::FENCE: { - if ((addr + length) > mem.size()) return iss::Err; - return iss::Ok; - } break; - case traits::RES: { - auto it = atomic_reservation.find(addr); - if (it != atomic_reservation.end() && it->second != 0) { - memset(data, 0xff, length); - atomic_reservation.erase(addr); - } else - memset(data, 0, length); - } break; - default: - return iss::Err; // assert("Not supported"); - } - return iss::Ok; - } catch (trap_access &ta) { - this->reg.trap_state = (1 << 31) | ta.id; - fault_data=ta.addr; - return iss::Err; - } -} - -template -iss::status riscv_hart_mu_p::write(const address_type type, const access_type access, const uint32_t space, - const uint64_t addr, const unsigned length, const uint8_t *const data) { -#ifndef NDEBUG - const char *prefix = (access && iss::access_type::DEBUG) ? "debug " : ""; - switch (length) { - case 8: - LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint64_t *)&data[0] << std::dec - << ") @addr 0x" << std::hex << addr; - break; - case 4: - LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint32_t *)&data[0] << std::dec - << ") @addr 0x" << std::hex << addr; - break; - case 2: - LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint16_t *)&data[0] << std::dec - << ") @addr 0x" << std::hex << addr; - break; - case 1: - LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << (uint16_t)data[0] << std::dec - << ") @addr 0x" << std::hex << addr; - break; - default: - LOG(TRACE) << prefix << "write of " << length << " bytes @addr " << addr; - } -#endif - try { - switch (space) { - case traits::MEM: { - if(FEAT & FEAT_PMP){ - if(!pmp_check(access, addr, length) && (access&access_type::DEBUG) != access_type::DEBUG) { - fault_data = addr; - if (access && iss::access_type::DEBUG) throw trap_access(0, addr); - this->reg.trap_state = (1 << 31) | (7 << 16); // issue trap 1 - return iss::Err; - } - } - if (unlikely((access && iss::access_type::FETCH) && (addr & 0x1) == 1)) { - fault_data = addr; - if (access && iss::access_type::DEBUG) throw trap_access(0, addr); - this->reg.trap_state = (1 << 31); // issue trap 0 - return iss::Err; - } - try { - if(length>1 && (addr&(length-1)) && (access&access_type::DEBUG) != access_type::DEBUG){ - this->reg.trap_state = 1<<31 | 6<<16; - fault_data=addr; - return iss::Err; - } - auto phys_addr = type==iss::address_type::PHYSICAL?phys_addr_t{access, space, addr}:BASE::v2p(iss::addr_t{access, type, space, addr}); - auto res = iss::Err; - if(access != access_type::FETCH && memfn_range.size()){ - auto it = std::find_if(std::begin(memfn_range), std::end(memfn_range), [phys_addr](std::tuple const& a){ - return std::get<0>(a)<=phys_addr.val && (std::get<0>(a)+std::get<1>(a))>phys_addr.val; - }); - if(it!=std::end(memfn_range)) { - auto idx = std::distance(std::begin(memfn_range), it); - res = memfn_write[idx]( phys_addr, length, data); - } else - res = write_mem( phys_addr, length, data); - } else { - res = write_mem( phys_addr, length, data); - } - if (unlikely(res != iss::Ok)) { - this->reg.trap_state = (1 << 31) | (7 << 16); // issue trap 7 (Store/AMO access fault) - fault_data=addr; - } - return res; - } catch (trap_access &ta) { - this->reg.trap_state = (1 << 31) | ta.id; - fault_data=ta.addr; - return iss::Err; - } - - phys_addr_t paddr = BASE::v2p(iss::addr_t{access, type, space, addr}); - if ((paddr.val + length) > mem.size()) return iss::Err; - switch (paddr.val) { - case 0x10013000: // UART0 base, TXFIFO reg - case 0x10023000: // UART1 base, TXFIFO reg - uart_buf << (char)data[0]; - if (((char)data[0]) == '\n' || data[0] == 0) { - // LOG(INFO)<<"UART"<<((paddr.val>>16)&0x3)<<" send - // '"<::CSR: { - if (length != sizeof(reg_t)) return iss::Err; - return write_csr(addr, *reinterpret_cast(data)); - } break; - case traits::FENCE: { - if ((addr + length) > mem.size()) return iss::Err; - switch (addr) { - case 2: - case 3: { - ptw.clear(); - auto tvm = state.mstatus.TVM; - return iss::Ok; - } - } - } break; - case traits::RES: { - atomic_reservation[addr] = data[0]; - } break; - default: - return iss::Err; - } - return iss::Ok; - } catch (trap_access &ta) { - this->reg.trap_state = (1 << 31) | ta.id; - fault_data=ta.addr; - return iss::Err; - } -} - -template iss::status riscv_hart_mu_p::read_csr(unsigned addr, reg_t &val) { - if (addr >= csr.size()) return iss::Err; - auto req_priv_lvl = (addr >> 8) & 0x3; - if (this->reg.PRIV < req_priv_lvl) // not having required privileges - throw illegal_instruction_fault(this->fault_data); - auto it = csr_rd_cb.find(addr); - if (it == csr_rd_cb.end() || !it->second) // non existent register - throw illegal_instruction_fault(this->fault_data); - return (this->*(it->second))(addr, val); -} - -template iss::status riscv_hart_mu_p::write_csr(unsigned addr, reg_t val) { - if (addr >= csr.size()) return iss::Err; - auto req_priv_lvl = (addr >> 8) & 0x3; - if (this->reg.PRIV < req_priv_lvl) // not having required privileges - throw illegal_instruction_fault(this->fault_data); - if((addr&0xc00)==0xc00) // writing to read-only region - throw illegal_instruction_fault(this->fault_data); - auto it = csr_wr_cb.find(addr); - if (it == csr_wr_cb.end() || !it->second) // non existent register - throw illegal_instruction_fault(this->fault_data); - return (this->*(it->second))(addr, val); -} - -template iss::status riscv_hart_mu_p::read_csr_reg(unsigned addr, reg_t &val) { - val = csr[addr]; - return iss::Ok; -} - -template iss::status riscv_hart_mu_p::read_null(unsigned addr, reg_t &val) { - val = 0; - return iss::Ok; -} - -template iss::status riscv_hart_mu_p::write_csr_reg(unsigned addr, reg_t val) { - csr[addr] = val; - return iss::Ok; -} - -template iss::status riscv_hart_mu_p::read_cycle(unsigned addr, reg_t &val) { - auto cycle_val = this->reg.icount + cycle_offset; - if (addr == mcycle) { - val = static_cast(cycle_val); - } else if (addr == mcycleh) { - if (sizeof(typename traits::reg_t) != 4) return iss::Err; - val = static_cast(cycle_val >> 32); - } - return iss::Ok; -} - -template iss::status riscv_hart_mu_p::write_cycle(unsigned addr, reg_t val) { - if (sizeof(typename traits::reg_t) != 4) { - if (addr == mcycleh) - return iss::Err; - mcycle_csr = static_cast(val); - } else { - if (addr == mcycle) { - mcycle_csr = (mcycle_csr & 0xffffffff00000000) + val; - } else { - mcycle_csr = (static_cast(val)<<32) + (mcycle_csr & 0xffffffff); - } - } - cycle_offset = mcycle_csr-this->reg.icount; // TODO: relying on wrap-around - return iss::Ok; -} - -template iss::status riscv_hart_mu_p::read_instret(unsigned addr, reg_t &val) { - if ((addr&0xff) == (minstret&0xff)) { - val = static_cast(this->reg.instret); - } else if ((addr&0xff) == (minstreth&0xff)) { - if (sizeof(typename traits::reg_t) != 4) return iss::Err; - val = static_cast(this->reg.instret >> 32); - } - return iss::Ok; -} - -template iss::status riscv_hart_mu_p::write_instret(unsigned addr, reg_t val) { - if (sizeof(typename traits::reg_t) != 4) { - if ((addr&0xff) == (minstreth&0xff)) - return iss::Err; - this->reg.instret = static_cast(val); - } else { - if ((addr&0xff) == (minstret&0xff)) { - this->reg.instret = (this->reg.instret & 0xffffffff00000000) + val; - } else { - this->reg.instret = (static_cast(val)<<32) + (this->reg.instret & 0xffffffff); - } - } - this->reg.instret--; - return iss::Ok; -} - -template iss::status riscv_hart_mu_p::read_time(unsigned addr, reg_t &val) { - uint64_t time_val = this->reg.icount / (100000000 / 32768 - 1); //-> ~3052; - if (addr == time) { - val = static_cast(time_val); - } else if (addr == timeh) { - if (sizeof(typename traits::reg_t) != 4) return iss::Err; - val = static_cast(time_val >> 32); - } - return iss::Ok; -} - -template iss::status riscv_hart_mu_p::read_tvec(unsigned addr, reg_t &val) { - val = csr[addr] & ~2; - return iss::Ok; -} -template iss::status riscv_hart_mu_p::read_status(unsigned addr, reg_t &val) { - auto req_priv_lvl = (addr >> 8) & 0x3; - val = state.mstatus & hart_state_type::get_mask(req_priv_lvl); - return iss::Ok; -} - -template iss::status riscv_hart_mu_p::write_status(unsigned addr, reg_t val) { - auto req_priv_lvl = (addr >> 8) & 0x3; - state.write_mstatus(val, req_priv_lvl); - check_interrupt(); - return iss::Ok; -} - -template iss::status riscv_hart_mu_p::write_cause(unsigned addr, reg_t val) { - csr[addr] = val & ((1UL<<(traits::XLEN-1))|(mcause_max_irq-1)); - return iss::Ok; -} - -template iss::status riscv_hart_mu_p::read_hartid(unsigned addr, reg_t &val) { - val = mhartid_reg; - return iss::Ok; -} - -template iss::status riscv_hart_mu_p::read_ie(unsigned addr, reg_t &val) { - auto mask = get_irq_mask((addr >> 8) & 0x3); - val = csr[mie] & mask; - if(this->reg.PRIV!=3) - val &= csr[mideleg]; - return iss::Ok; -} - -template iss::status riscv_hart_mu_p::write_ie(unsigned addr, reg_t val) { - auto mask = get_irq_mask((addr >> 8) & 0x3); - csr[mie] = (csr[mie] & ~mask) | (val & mask); - check_interrupt(); - return iss::Ok; -} - -template iss::status riscv_hart_mu_p::read_ip(unsigned addr, reg_t &val) { - auto mask = get_irq_mask((addr >> 8) & 0x3); - val = csr[mip] & mask; - if(this->reg.PRIV!=3) - val &= csr[mideleg]; - return iss::Ok; -} - -template iss::status riscv_hart_mu_p::write_ideleg(unsigned addr, reg_t val) { - auto mask = 0b000100010001; // only U mode supported - csr[mideleg] = (csr[mideleg] & ~mask) | (val & mask); - return iss::Ok; -} - -template iss::status riscv_hart_mu_p::write_edeleg(unsigned addr, reg_t val) { - auto mask = 0b1011001111110111; // bit 14/10 (reserved), bit 11 (Env call), and 3 (break) are hardwired to 0 - csr[medeleg] = (csr[medeleg] & ~mask) | (val & mask); - return iss::Ok; -} - -template iss::status riscv_hart_mu_p::write_epc(unsigned addr, reg_t val) { - csr[addr] = val & get_pc_mask(); - return iss::Ok; -} - -template iss::status riscv_hart_mu_p::write_dcsr_dcsr(unsigned addr, reg_t val) { - if(!debug_mode_active()) - throw illegal_instruction_fault(this->fault_data); - // +-------------- ebreakm - // | +---------- stepi - // | | +++----- cause - // | | ||| +- step - csr[addr] = val & 0b1000100111000100U; - return iss::Ok; -} - -template iss::status riscv_hart_mu_p::read_dcsr_reg(unsigned addr, reg_t &val) { - if(!debug_mode_active()) - throw illegal_instruction_fault(this->fault_data); - val = csr[addr]; - return iss::Ok; -} - -template iss::status riscv_hart_mu_p::write_dcsr_reg(unsigned addr, reg_t val) { - if(!debug_mode_active()) - throw illegal_instruction_fault(this->fault_data); - csr[addr] = val; - return iss::Ok; -} - -template iss::status riscv_hart_mu_p::read_dpc_reg(unsigned addr, reg_t &val) { - if(!debug_mode_active()) - throw illegal_instruction_fault(this->fault_data); - val = this->reg.DPC; - return iss::Ok; -} - -template iss::status riscv_hart_mu_p::write_dpc_reg(unsigned addr, reg_t val) { - if(!debug_mode_active()) - throw illegal_instruction_fault(this->fault_data); - this->reg.DPC = val; - return iss::Ok; -} - -template -iss::status riscv_hart_mu_p::write_intthresh(unsigned addr, reg_t val) { - csr[addr]= val &0xff; - return iss::Ok; -} - -template -iss::status riscv_hart_mu_p::read_mem(phys_addr_t paddr, unsigned length, uint8_t *const data) { - if(mem_read_cb) return mem_read_cb(paddr, length, data); - switch (paddr.val) { - case 0x0200BFF8: { // CLINT base, mtime reg - if (sizeof(reg_t) < length) return iss::Err; - reg_t time_val; - this->read_csr(time, time_val); - std::copy((uint8_t *)&time_val, ((uint8_t *)&time_val) + length, data); - } break; - case 0x10008000: { - const mem_type::page_type &p = mem(paddr.val / mem.page_size); - uint64_t offs = paddr.val & mem.page_addr_mask; - std::copy(p.data() + offs, p.data() + offs + length, data); - if (this->reg.icount > 30000) data[3] |= 0x80; - } break; - default: { - for(auto offs=0U; offs -iss::status riscv_hart_mu_p::write_mem(phys_addr_t paddr, unsigned length, const uint8_t *const data) { - if(mem_write_cb) return mem_write_cb(paddr, length, data); - switch (paddr.val) { - case 0x10013000: // UART0 base, TXFIFO reg - case 0x10023000: // UART1 base, TXFIFO reg - uart_buf << (char)data[0]; - if (((char)data[0]) == '\n' || data[0] == 0) { - LOG(INFO)<<"UART"<<((paddr.val>>16)&0x3)<<" send '"<::XLEN == 32 && paddr.val == (tohost + 4)) || - (traits::XLEN == 64 && paddr.val == tohost); - auto tohost_lower = - (traits::XLEN == 32 && paddr.val == tohost) || (traits::XLEN == 64 && paddr.val == tohost); - if (tohost_lower || tohost_upper) { - uint64_t hostvar = *reinterpret_cast(p.data() + (tohost & mem.page_addr_mask)); - if (tohost_upper || (tohost_lower && to_host_wr_cnt > 0)) { - switch (hostvar >> 48) { - case 0: - if (hostvar != 0x1) { - LOG(FATAL) << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar - << "), stopping simulation"; - } else { - LOG(INFO) << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar - << "), stopping simulation"; - } - this->reg.trap_state=std::numeric_limits::max(); - this->interrupt_sim=hostvar; - break; - //throw(iss::simulation_stopped(hostvar)); - case 0x0101: { - char c = static_cast(hostvar & 0xff); - if (c == '\n' || c == 0) { - LOG(INFO) << "tohost send '" << uart_buf.str() << "'"; - uart_buf.str(""); - } else - uart_buf << c; - to_host_wr_cnt = 0; - } break; - default: - break; - } - } else if (tohost_lower) - to_host_wr_cnt++; - } else if ((traits::XLEN == 32 && paddr.val == fromhost + 4) || - (traits::XLEN == 64 && paddr.val == fromhost)) { - uint64_t fhostvar = *reinterpret_cast(p.data() + (fromhost & mem.page_addr_mask)); - *reinterpret_cast(p.data() + (tohost & mem.page_addr_mask)) = fhostvar; - } - } - } - } - return iss::Ok; -} - -template -iss::status riscv_hart_mu_p::read_clic(uint64_t addr, unsigned length, uint8_t *const data) { - if(addr==cfg.clic_base) { // cliccfg - *data=clic_cfg_reg; - for(auto i=1; i=(cfg.clic_base+4) && (addr+length)<=(cfg.clic_base+8)){ // clicinfo - read_reg_uint32(addr, clic_info_reg, data, length); - } else if(addr>=(cfg.clic_base+0x40) && (addr+length)<=(cfg.clic_base+0x40+cfg.clic_num_trigger*4)){ // clicinttrig - auto offset = ((addr&0x7fff)-0x40)/4; - read_reg_uint32(addr, clic_inttrig_reg[offset], data, length); - } else if(addr>=(cfg.clic_base+0x1000) && (addr+length)<=(cfg.clic_base+0x1000+cfg.clic_num_irq*4)){ // clicintip/clicintie/clicintattr/clicintctl - auto offset = ((addr&0x7fff)-0x1000)/4; - read_reg_uint32(addr, clic_int_reg[offset].raw, data, length); - } else { - for(auto i = 0U; i -iss::status riscv_hart_mu_p::write_clic(uint64_t addr, unsigned length, const uint8_t *const data) { - if(addr==cfg.clic_base) { // cliccfg - clic_cfg_reg = *data; - clic_cfg_reg&= 0x7e; -// } else if(addr>=(cfg.clic_base+4) && (addr+length)<=(cfg.clic_base+4)){ // clicinfo -// write_uint32(addr, clic_info_reg, data, length); - } else if(addr>=(cfg.clic_base+0x40) && (addr+length)<=(cfg.clic_base+0x40+cfg.clic_num_trigger*4)){ // clicinttrig - auto offset = ((addr&0x7fff)-0x40)/4; - write_reg_uint32(addr, clic_inttrig_reg[offset], data, length); - } else if(addr>=(cfg.clic_base+0x1000) && (addr+length)<=(cfg.clic_base+0x1000+cfg.clic_num_irq*4)){ // clicintip/clicintie/clicintattr/clicintctl - auto offset = ((addr&0x7fff)-0x1000)/4; - write_reg_uint32(addr, clic_int_reg[offset].raw, data, length); - } - return iss::Ok; -} - -template inline void riscv_hart_mu_p::reset(uint64_t address) { - BASE::reset(address); - state.mstatus = hart_state_type::mstatus_reset_val; -} - -template void riscv_hart_mu_p::check_interrupt() { - auto ideleg = csr[mideleg]; - // Multiple simultaneous interrupts and traps at the same privilege level are - // handled in the following decreasing priority order: - // external interrupts, software interrupts, timer interrupts, then finally - // any synchronous traps. - auto ena_irq = csr[mip] & csr[mie]; - - bool mie = state.mstatus.MIE; - auto m_enabled = this->reg.PRIV < PRIV_M || mie; - auto enabled_interrupts = m_enabled ? ena_irq & ~ideleg : 0; - - if (enabled_interrupts != 0) { - int res = 0; - while ((enabled_interrupts & 1) == 0) { - enabled_interrupts >>= 1; - res++; - } - this->reg.pending_trap = res << 16 | 1; // 0x80 << 24 | (cause << 16) | trap_id - } -} - -template uint64_t riscv_hart_mu_p::enter_trap(uint64_t flags, uint64_t addr, uint64_t instr) { - // flags are ACTIVE[31:31], CAUSE[30:16], TRAPID[15:0] - // calculate and write mcause val - if(flags==std::numeric_limits::max()) flags=this->reg.trap_state; - auto trap_id = bit_sub<0, 16>(flags); - auto cause = bit_sub<16, 15>(flags); - if (trap_id == 0 && cause == 11) cause = 0x8 + this->reg.PRIV; // adjust environment call cause - // calculate effective privilege level - unsigned new_priv = PRIV_M; - if (trap_id == 0) { // exception - if (this->reg.PRIV != PRIV_M && ((csr[medeleg] >> cause) & 0x1) != 0) - new_priv = PRIV_U; - // store ret addr in xepc register - csr[uepc | (new_priv << 8)] = static_cast(addr); // store actual address instruction of exception - /* - * write mtval if new_priv=M_MODE, spec says: - * When a hardware breakpoint is triggered, or an instruction-fetch, load, - * or store address-misaligned, - * access, or page-fault exception occurs, mtval is written with the - * faulting effective address. - */ - switch(cause){ - case 0: - csr[utval | (new_priv << 8)] = static_cast(addr); - break; - case 2: - csr[utval | (new_priv << 8)] = (instr & 0x3)==3?instr:instr&0xffff; - break; - case 3: - if((FEAT & FEAT_DEBUG) && (csr[dcsr] & 0x8000)) { - this->reg.DPC = addr; - csr[dcsr] = (csr[dcsr] & ~0x1c3) | (1<<6) | PRIV_M; //FIXME: cause should not be 4 (stepi) - new_priv = this->reg.PRIV | PRIV_D; - } else { - csr[utval | (new_priv << 8)] = addr; - } - break; - case 4: - case 6: - case 7: - csr[utval | (new_priv << 8)] = fault_data; - break; - default: - csr[utval | (new_priv << 8)] = 0; - } - fault_data = 0; - } else { - if (this->reg.PRIV != PRIV_M && ((csr[mideleg] >> cause) & 0x1) != 0) - new_priv = PRIV_U; - csr[uepc | (new_priv << 8)] = this->reg.NEXT_PC; // store next address if interrupt - this->reg.pending_trap = 0; - } - size_t adr = ucause | (new_priv << 8); - csr[adr] = (trap_id << (traits::XLEN-1)) + cause; - // update mstatus - // xPP field of mstatus is written with the active privilege mode at the time - // of the trap; the x PIE field of mstatus - // is written with the value of the active interrupt-enable bit at the time of - // the trap; and the x IE field of mstatus - // is cleared - // store the actual privilege level in yPP and store interrupt enable flags - switch (new_priv) { - case PRIV_M: - state.mstatus.MPP = this->reg.PRIV; - state.mstatus.MPIE = state.mstatus.MIE; - state.mstatus.MIE = false; - break; - case PRIV_U: - state.mstatus.UPIE = state.mstatus.UIE; - state.mstatus.UIE = false; - break; - default: - break; - } - - // get trap vector - auto ivec = csr[utvec | (new_priv << 8)]; - // calculate addr// set NEXT_PC to trap addressess to jump to based on MODE - // bits in mtvec - this->reg.NEXT_PC = ivec & ~0x3UL; - if ((ivec & 0x1) == 1 && trap_id != 0) this->reg.NEXT_PC += 4 * cause; - std::array buffer; - sprintf(buffer.data(), "0x%016lx", addr); - if((flags&0xffffffff) != 0xffffffff) - CLOG(INFO, disass) << (trap_id ? "Interrupt" : "Trap") << " with cause '" - << (trap_id ? irq_str[cause] : trap_str[cause]) << "' (" << cause << ")" - << " at address " << buffer.data() << " occurred, changing privilege level from " - << lvl[this->reg.PRIV] << " to " << lvl[new_priv]; - // reset trap state - this->reg.PRIV = new_priv; - this->reg.trap_state = 0; - return this->reg.NEXT_PC; -} - -template uint64_t riscv_hart_mu_p::leave_trap(uint64_t flags) { - auto cur_priv = this->reg.PRIV; - auto inst_priv = (flags & 0x3)? 3:0; - if(inst_priv>cur_priv){ - auto trap_val = 0x80ULL << 24 | (2 << 16); // illegal instruction - this->reg.trap_state = trap_val; - this->reg.NEXT_PC = std::numeric_limits::max(); - } else { - auto status = state.mstatus; - // pop the relevant lower-privilege interrupt enable and privilege mode stack - // clear respective yIE - switch (inst_priv) { - case PRIV_M: - this->reg.PRIV = state.mstatus.MPP; - state.mstatus.MPP = 0; // clear mpp to U mode - state.mstatus.MIE = state.mstatus.MPIE; - state.mstatus.MPIE = 1; - break; - case PRIV_U: - this->reg.PRIV = 0; - state.mstatus.UIE = state.mstatus.UPIE; - state.mstatus.UPIE = 1; - break; - } - // sets the pc to the value stored in the x epc register. - this->reg.NEXT_PC = csr[uepc | inst_priv << 8]; - CLOG(INFO, disass) << "Executing xRET , changing privilege level from " << lvl[cur_priv] << " to " - << lvl[this->reg.PRIV]; - check_interrupt(); - } - return this->reg.NEXT_PC; -} - -} // namespace arch -} // namespace iss - -#endif /* _RISCV_HART_MU_P_H */ diff --git a/incl/iss/arch/tgc_mapper.h b/incl/iss/arch/tgc_mapper.h deleted file mode 100644 index 7173d7b..0000000 --- a/incl/iss/arch/tgc_mapper.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef _ISS_ARCH_TGC_MAPPER_H -#define _ISS_ARCH_TGC_MAPPER_H - -#include "riscv_hart_m_p.h" -#include "tgc_c.h" -using tgc_c_plat_type = iss::arch::riscv_hart_m_p; -#ifdef CORE_TGC_B -#include "riscv_hart_m_p.h" -#include "tgc_b.h" -using tgc_b_plat_type = iss::arch::riscv_hart_m_p; -#endif -#ifdef CORE_TGC_C_XRB_NN -#include "riscv_hart_m_p.h" -#include "tgc_c_xrb_nn.h" -using tgc_c_xrb_nn_plat_type = iss::arch::riscv_hart_m_p; -#endif -#ifdef CORE_TGC_D -#include "riscv_hart_mu_p.h" -#include "tgc_d.h" -using tgc_d_plat_type = iss::arch::riscv_hart_mu_p; -#endif -#ifdef CORE_TGC_D_XRB_MAC -#include "riscv_hart_mu_p.h" -#include "tgc_d_xrb_mac.h" -using tgc_d_xrb_mac_plat_type = iss::arch::riscv_hart_mu_p; -#endif -#ifdef CORE_TGC_D_XRB_NN -#include "riscv_hart_mu_p.h" -#include "tgc_d_xrb_nn.h" -using tgc_d_xrb_nn_plat_type = iss::arch::riscv_hart_mu_p; -#endif -#ifdef CORE_TGC_E -#include "riscv_hart_mu_p.h" -#include "tgc_e.h" -using tgc_e_plat_type = iss::arch::riscv_hart_mu_p; -#endif -#ifdef CORE_TGC_X -#include "riscv_hart_mu_p.h" -#include "tgc_x.h" -using tgc_x_plat_type = iss::arch::riscv_hart_mu_p; -#endif - -#endif diff --git a/softfloat/CMakeLists.txt b/softfloat/CMakeLists.txt index c4ea4bd..b2ff9df 100644 --- a/softfloat/CMakeLists.txt +++ b/softfloat/CMakeLists.txt @@ -8,7 +8,7 @@ project("sotfloat" VERSION 3.0.0) # Set the version number of your project here (format is MAJOR.MINOR.PATCHLEVEL - e.g. 1.0.0) set(VERSION "3e") -include(Common) +#include(Common) include(GNUInstallDirs) set(SPECIALIZATION RISCV) diff --git a/softfloat/build/Linux-386-GCC/platform.h b/softfloat/build/Linux-386-GCC/platform.h index 420aa4e..eb224b1 100644 --- a/softfloat/build/Linux-386-GCC/platform.h +++ b/softfloat/build/Linux-386-GCC/platform.h @@ -35,11 +35,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ /*---------------------------------------------------------------------------- -*----------------------------------------------------------------------------*/ + *----------------------------------------------------------------------------*/ #define LITTLEENDIAN 1 /*---------------------------------------------------------------------------- -*----------------------------------------------------------------------------*/ + *----------------------------------------------------------------------------*/ #ifdef __GNUC_STDC_INLINE__ #define INLINE inline #else @@ -47,7 +47,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endif /*---------------------------------------------------------------------------- -*----------------------------------------------------------------------------*/ + *----------------------------------------------------------------------------*/ #define SOFTFLOAT_BUILTIN_CLZ 1 #include "opts-GCC.h" - diff --git a/softfloat/build/Linux-386-SSE2-GCC/platform.h b/softfloat/build/Linux-386-SSE2-GCC/platform.h index 420aa4e..eb224b1 100644 --- a/softfloat/build/Linux-386-SSE2-GCC/platform.h +++ b/softfloat/build/Linux-386-SSE2-GCC/platform.h @@ -35,11 +35,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ /*---------------------------------------------------------------------------- -*----------------------------------------------------------------------------*/ + *----------------------------------------------------------------------------*/ #define LITTLEENDIAN 1 /*---------------------------------------------------------------------------- -*----------------------------------------------------------------------------*/ + *----------------------------------------------------------------------------*/ #ifdef __GNUC_STDC_INLINE__ #define INLINE inline #else @@ -47,7 +47,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endif /*---------------------------------------------------------------------------- -*----------------------------------------------------------------------------*/ + *----------------------------------------------------------------------------*/ #define SOFTFLOAT_BUILTIN_CLZ 1 #include "opts-GCC.h" - diff --git a/softfloat/build/Linux-ARM-VFPv2-GCC/platform.h b/softfloat/build/Linux-ARM-VFPv2-GCC/platform.h index 420aa4e..eb224b1 100644 --- a/softfloat/build/Linux-ARM-VFPv2-GCC/platform.h +++ b/softfloat/build/Linux-ARM-VFPv2-GCC/platform.h @@ -35,11 +35,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ /*---------------------------------------------------------------------------- -*----------------------------------------------------------------------------*/ + *----------------------------------------------------------------------------*/ #define LITTLEENDIAN 1 /*---------------------------------------------------------------------------- -*----------------------------------------------------------------------------*/ + *----------------------------------------------------------------------------*/ #ifdef __GNUC_STDC_INLINE__ #define INLINE inline #else @@ -47,7 +47,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endif /*---------------------------------------------------------------------------- -*----------------------------------------------------------------------------*/ + *----------------------------------------------------------------------------*/ #define SOFTFLOAT_BUILTIN_CLZ 1 #include "opts-GCC.h" - diff --git a/softfloat/build/Linux-x86_64-GCC/platform.h b/softfloat/build/Linux-x86_64-GCC/platform.h index 92c3044..630cb43 100644 --- a/softfloat/build/Linux-x86_64-GCC/platform.h +++ b/softfloat/build/Linux-x86_64-GCC/platform.h @@ -35,11 +35,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ /*---------------------------------------------------------------------------- -*----------------------------------------------------------------------------*/ + *----------------------------------------------------------------------------*/ #define LITTLEENDIAN 1 /*---------------------------------------------------------------------------- -*----------------------------------------------------------------------------*/ + *----------------------------------------------------------------------------*/ #ifdef __GNUC_STDC_INLINE__ //#define INLINE inline #define INLINE static @@ -48,10 +48,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endif /*---------------------------------------------------------------------------- -*----------------------------------------------------------------------------*/ + *----------------------------------------------------------------------------*/ #ifdef __GNUC__ #define SOFTFLOAT_BUILTIN_CLZ 1 #define SOFTFLOAT_INTRINSIC_INT128 1 #endif #include "opts-GCC.h" - diff --git a/softfloat/build/Win32-MinGW/platform.h b/softfloat/build/Win32-MinGW/platform.h index 420aa4e..eb224b1 100644 --- a/softfloat/build/Win32-MinGW/platform.h +++ b/softfloat/build/Win32-MinGW/platform.h @@ -35,11 +35,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ /*---------------------------------------------------------------------------- -*----------------------------------------------------------------------------*/ + *----------------------------------------------------------------------------*/ #define LITTLEENDIAN 1 /*---------------------------------------------------------------------------- -*----------------------------------------------------------------------------*/ + *----------------------------------------------------------------------------*/ #ifdef __GNUC_STDC_INLINE__ #define INLINE inline #else @@ -47,7 +47,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endif /*---------------------------------------------------------------------------- -*----------------------------------------------------------------------------*/ + *----------------------------------------------------------------------------*/ #define SOFTFLOAT_BUILTIN_CLZ 1 #include "opts-GCC.h" - diff --git a/softfloat/build/Win32-SSE2-MinGW/platform.h b/softfloat/build/Win32-SSE2-MinGW/platform.h index 420aa4e..eb224b1 100644 --- a/softfloat/build/Win32-SSE2-MinGW/platform.h +++ b/softfloat/build/Win32-SSE2-MinGW/platform.h @@ -35,11 +35,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ /*---------------------------------------------------------------------------- -*----------------------------------------------------------------------------*/ + *----------------------------------------------------------------------------*/ #define LITTLEENDIAN 1 /*---------------------------------------------------------------------------- -*----------------------------------------------------------------------------*/ + *----------------------------------------------------------------------------*/ #ifdef __GNUC_STDC_INLINE__ #define INLINE inline #else @@ -47,7 +47,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endif /*---------------------------------------------------------------------------- -*----------------------------------------------------------------------------*/ + *----------------------------------------------------------------------------*/ #define SOFTFLOAT_BUILTIN_CLZ 1 #include "opts-GCC.h" - diff --git a/softfloat/build/Win64-MinGW-w64/platform.h b/softfloat/build/Win64-MinGW-w64/platform.h index 2fccb6c..737a708 100644 --- a/softfloat/build/Win64-MinGW-w64/platform.h +++ b/softfloat/build/Win64-MinGW-w64/platform.h @@ -35,11 +35,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ /*---------------------------------------------------------------------------- -*----------------------------------------------------------------------------*/ + *----------------------------------------------------------------------------*/ #define LITTLEENDIAN 1 /*---------------------------------------------------------------------------- -*----------------------------------------------------------------------------*/ + *----------------------------------------------------------------------------*/ #ifdef __GNUC_STDC_INLINE__ #define INLINE inline #else @@ -47,8 +47,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endif /*---------------------------------------------------------------------------- -*----------------------------------------------------------------------------*/ + *----------------------------------------------------------------------------*/ #define SOFTFLOAT_BUILTIN_CLZ 1 #define SOFTFLOAT_INTRINSIC_INT128 1 #include "opts-GCC.h" - diff --git a/softfloat/build/template-FAST_INT64/platform.h b/softfloat/build/template-FAST_INT64/platform.h index b63e2a7..b59e6c5 100644 --- a/softfloat/build/template-FAST_INT64/platform.h +++ b/softfloat/build/template-FAST_INT64/platform.h @@ -37,14 +37,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Edit lines marked with `==>'. See "SoftFloat-source.html". /*---------------------------------------------------------------------------- -*----------------------------------------------------------------------------*/ -==> #define LITTLEENDIAN 1 + *----------------------------------------------------------------------------*/ +== > #define LITTLEENDIAN 1 -/*---------------------------------------------------------------------------- -*----------------------------------------------------------------------------*/ -==> #define INLINE inline - -/*---------------------------------------------------------------------------- -*----------------------------------------------------------------------------*/ -==> #define THREAD_LOCAL _Thread_local + /*---------------------------------------------------------------------------- + *----------------------------------------------------------------------------*/ + == > #define INLINE inline + /*---------------------------------------------------------------------------- + *----------------------------------------------------------------------------*/ + == > #define THREAD_LOCAL _Thread_local diff --git a/softfloat/build/template-not-FAST_INT64/platform.h b/softfloat/build/template-not-FAST_INT64/platform.h index b63e2a7..b59e6c5 100644 --- a/softfloat/build/template-not-FAST_INT64/platform.h +++ b/softfloat/build/template-not-FAST_INT64/platform.h @@ -37,14 +37,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Edit lines marked with `==>'. See "SoftFloat-source.html". /*---------------------------------------------------------------------------- -*----------------------------------------------------------------------------*/ -==> #define LITTLEENDIAN 1 + *----------------------------------------------------------------------------*/ +== > #define LITTLEENDIAN 1 -/*---------------------------------------------------------------------------- -*----------------------------------------------------------------------------*/ -==> #define INLINE inline - -/*---------------------------------------------------------------------------- -*----------------------------------------------------------------------------*/ -==> #define THREAD_LOCAL _Thread_local + /*---------------------------------------------------------------------------- + *----------------------------------------------------------------------------*/ + == > #define INLINE inline + /*---------------------------------------------------------------------------- + *----------------------------------------------------------------------------*/ + == > #define THREAD_LOCAL _Thread_local diff --git a/softfloat/source/8086-SSE/specialize.h b/softfloat/source/8086-SSE/specialize.h index 5fe119a..23b1632 100644 --- a/softfloat/source/8086-SSE/specialize.h +++ b/softfloat/source/8086-SSE/specialize.h @@ -37,10 +37,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef specialize_h #define specialize_h 1 -#include -#include #include "primitiveTypes.h" #include "softfloat.h" +#include +#include /*---------------------------------------------------------------------------- | Default value for 'softfloat_detectTininess'. @@ -53,21 +53,21 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *----------------------------------------------------------------------------*/ #define ui32_fromPosOverflow 0xFFFFFFFF #define ui32_fromNegOverflow 0xFFFFFFFF -#define ui32_fromNaN 0xFFFFFFFF -#define i32_fromPosOverflow (-0x7FFFFFFF - 1) -#define i32_fromNegOverflow (-0x7FFFFFFF - 1) -#define i32_fromNaN (-0x7FFFFFFF - 1) +#define ui32_fromNaN 0xFFFFFFFF +#define i32_fromPosOverflow (-0x7FFFFFFF - 1) +#define i32_fromNegOverflow (-0x7FFFFFFF - 1) +#define i32_fromNaN (-0x7FFFFFFF - 1) /*---------------------------------------------------------------------------- | The values to return on conversions to 64-bit integer formats that raise an | invalid exception. *----------------------------------------------------------------------------*/ -#define ui64_fromPosOverflow UINT64_C( 0xFFFFFFFFFFFFFFFF ) -#define ui64_fromNegOverflow UINT64_C( 0xFFFFFFFFFFFFFFFF ) -#define ui64_fromNaN UINT64_C( 0xFFFFFFFFFFFFFFFF ) -#define i64_fromPosOverflow (-INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1) -#define i64_fromNegOverflow (-INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1) -#define i64_fromNaN (-INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1) +#define ui64_fromPosOverflow UINT64_C(0xFFFFFFFFFFFFFFFF) +#define ui64_fromNegOverflow UINT64_C(0xFFFFFFFFFFFFFFFF) +#define ui64_fromNaN UINT64_C(0xFFFFFFFFFFFFFFFF) +#define i64_fromPosOverflow (-INT64_C(0x7FFFFFFFFFFFFFFF) - 1) +#define i64_fromNegOverflow (-INT64_C(0x7FFFFFFFFFFFFFFF) - 1) +#define i64_fromNaN (-INT64_C(0x7FFFFFFFFFFFFFFF) - 1) /*---------------------------------------------------------------------------- | "Common NaN" structure, used to transfer NaN representations from one format @@ -92,7 +92,7 @@ struct commonNaN { | 16-bit floating-point signaling NaN. | Note: This macro evaluates its argument more than once. *----------------------------------------------------------------------------*/ -#define softfloat_isSigNaNF16UI( uiA ) ((((uiA) & 0x7E00) == 0x7C00) && ((uiA) & 0x01FF)) +#define softfloat_isSigNaNF16UI(uiA) ((((uiA)&0x7E00) == 0x7C00) && ((uiA)&0x01FF)) /*---------------------------------------------------------------------------- | Assuming 'uiA' has the bit pattern of a 16-bit floating-point NaN, converts @@ -100,13 +100,13 @@ struct commonNaN { | location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid | exception is raised. *----------------------------------------------------------------------------*/ -void softfloat_f16UIToCommonNaN( uint_fast16_t uiA, struct commonNaN *zPtr ); +void softfloat_f16UIToCommonNaN(uint_fast16_t uiA, struct commonNaN* zPtr); /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by 'aPtr' into a 16-bit floating-point | NaN, and returns the bit pattern of this value as an unsigned integer. *----------------------------------------------------------------------------*/ -uint_fast16_t softfloat_commonNaNToF16UI( const struct commonNaN *aPtr ); +uint_fast16_t softfloat_commonNaNToF16UI(const struct commonNaN* aPtr); /*---------------------------------------------------------------------------- | Interpreting 'uiA' and 'uiB' as the bit patterns of two 16-bit floating- @@ -114,8 +114,7 @@ uint_fast16_t softfloat_commonNaNToF16UI( const struct commonNaN *aPtr ); | the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a | signaling NaN, the invalid exception is raised. *----------------------------------------------------------------------------*/ -uint_fast16_t - softfloat_propagateNaNF16UI( uint_fast16_t uiA, uint_fast16_t uiB ); +uint_fast16_t softfloat_propagateNaNF16UI(uint_fast16_t uiA, uint_fast16_t uiB); /*---------------------------------------------------------------------------- | The bit pattern for a default generated 32-bit floating-point NaN. @@ -127,7 +126,7 @@ uint_fast16_t | 32-bit floating-point signaling NaN. | Note: This macro evaluates its argument more than once. *----------------------------------------------------------------------------*/ -#define softfloat_isSigNaNF32UI( uiA ) ((((uiA) & 0x7FC00000) == 0x7F800000) && ((uiA) & 0x003FFFFF)) +#define softfloat_isSigNaNF32UI(uiA) ((((uiA)&0x7FC00000) == 0x7F800000) && ((uiA)&0x003FFFFF)) /*---------------------------------------------------------------------------- | Assuming 'uiA' has the bit pattern of a 32-bit floating-point NaN, converts @@ -135,13 +134,13 @@ uint_fast16_t | location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid | exception is raised. *----------------------------------------------------------------------------*/ -void softfloat_f32UIToCommonNaN( uint_fast32_t uiA, struct commonNaN *zPtr ); +void softfloat_f32UIToCommonNaN(uint_fast32_t uiA, struct commonNaN* zPtr); /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by 'aPtr' into a 32-bit floating-point | NaN, and returns the bit pattern of this value as an unsigned integer. *----------------------------------------------------------------------------*/ -uint_fast32_t softfloat_commonNaNToF32UI( const struct commonNaN *aPtr ); +uint_fast32_t softfloat_commonNaNToF32UI(const struct commonNaN* aPtr); /*---------------------------------------------------------------------------- | Interpreting 'uiA' and 'uiB' as the bit patterns of two 32-bit floating- @@ -149,20 +148,20 @@ uint_fast32_t softfloat_commonNaNToF32UI( const struct commonNaN *aPtr ); | the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a | signaling NaN, the invalid exception is raised. *----------------------------------------------------------------------------*/ -uint_fast32_t - softfloat_propagateNaNF32UI( uint_fast32_t uiA, uint_fast32_t uiB ); +uint_fast32_t softfloat_propagateNaNF32UI(uint_fast32_t uiA, uint_fast32_t uiB); /*---------------------------------------------------------------------------- | The bit pattern for a default generated 64-bit floating-point NaN. *----------------------------------------------------------------------------*/ -#define defaultNaNF64UI UINT64_C( 0xFFF8000000000000 ) +#define defaultNaNF64UI UINT64_C(0xFFF8000000000000) /*---------------------------------------------------------------------------- | Returns true when 64-bit unsigned integer 'uiA' has the bit pattern of a | 64-bit floating-point signaling NaN. | Note: This macro evaluates its argument more than once. *----------------------------------------------------------------------------*/ -#define softfloat_isSigNaNF64UI( uiA ) ((((uiA) & UINT64_C( 0x7FF8000000000000 )) == UINT64_C( 0x7FF0000000000000 )) && ((uiA) & UINT64_C( 0x0007FFFFFFFFFFFF ))) +#define softfloat_isSigNaNF64UI(uiA) \ + ((((uiA)&UINT64_C(0x7FF8000000000000)) == UINT64_C(0x7FF0000000000000)) && ((uiA)&UINT64_C(0x0007FFFFFFFFFFFF))) /*---------------------------------------------------------------------------- | Assuming 'uiA' has the bit pattern of a 64-bit floating-point NaN, converts @@ -170,13 +169,13 @@ uint_fast32_t | location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid | exception is raised. *----------------------------------------------------------------------------*/ -void softfloat_f64UIToCommonNaN( uint_fast64_t uiA, struct commonNaN *zPtr ); +void softfloat_f64UIToCommonNaN(uint_fast64_t uiA, struct commonNaN* zPtr); /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by 'aPtr' into a 64-bit floating-point | NaN, and returns the bit pattern of this value as an unsigned integer. *----------------------------------------------------------------------------*/ -uint_fast64_t softfloat_commonNaNToF64UI( const struct commonNaN *aPtr ); +uint_fast64_t softfloat_commonNaNToF64UI(const struct commonNaN* aPtr); /*---------------------------------------------------------------------------- | Interpreting 'uiA' and 'uiB' as the bit patterns of two 64-bit floating- @@ -184,14 +183,13 @@ uint_fast64_t softfloat_commonNaNToF64UI( const struct commonNaN *aPtr ); | the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a | signaling NaN, the invalid exception is raised. *----------------------------------------------------------------------------*/ -uint_fast64_t - softfloat_propagateNaNF64UI( uint_fast64_t uiA, uint_fast64_t uiB ); +uint_fast64_t softfloat_propagateNaNF64UI(uint_fast64_t uiA, uint_fast64_t uiB); /*---------------------------------------------------------------------------- | The bit pattern for a default generated 80-bit extended floating-point NaN. *----------------------------------------------------------------------------*/ #define defaultNaNExtF80UI64 0xFFFF -#define defaultNaNExtF80UI0 UINT64_C( 0xC000000000000000 ) +#define defaultNaNExtF80UI0 UINT64_C(0xC000000000000000) /*---------------------------------------------------------------------------- | Returns true when the 80-bit unsigned integer formed from concatenating @@ -199,7 +197,8 @@ uint_fast64_t | floating-point signaling NaN. | Note: This macro evaluates its arguments more than once. *----------------------------------------------------------------------------*/ -#define softfloat_isSigNaNExtF80UI( uiA64, uiA0 ) ((((uiA64) & 0x7FFF) == 0x7FFF) && ! ((uiA0) & UINT64_C( 0x4000000000000000 )) && ((uiA0) & UINT64_C( 0x3FFFFFFFFFFFFFFF ))) +#define softfloat_isSigNaNExtF80UI(uiA64, uiA0) \ + ((((uiA64)&0x7FFF) == 0x7FFF) && !((uiA0)&UINT64_C(0x4000000000000000)) && ((uiA0)&UINT64_C(0x3FFFFFFFFFFFFFFF))) #ifdef SOFTFLOAT_FAST_INT64 @@ -215,16 +214,14 @@ uint_fast64_t | location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid | exception is raised. *----------------------------------------------------------------------------*/ -void - softfloat_extF80UIToCommonNaN( - uint_fast16_t uiA64, uint_fast64_t uiA0, struct commonNaN *zPtr ); +void softfloat_extF80UIToCommonNaN(uint_fast16_t uiA64, uint_fast64_t uiA0, struct commonNaN* zPtr); /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by 'aPtr' into an 80-bit extended | floating-point NaN, and returns the bit pattern of this value as an unsigned | integer. *----------------------------------------------------------------------------*/ -struct uint128 softfloat_commonNaNToExtF80UI( const struct commonNaN *aPtr ); +struct uint128 softfloat_commonNaNToExtF80UI(const struct commonNaN* aPtr); /*---------------------------------------------------------------------------- | Interpreting the unsigned integer formed from concatenating 'uiA64' and @@ -235,19 +232,13 @@ struct uint128 softfloat_commonNaNToExtF80UI( const struct commonNaN *aPtr ); | result. If either original floating-point value is a signaling NaN, the | invalid exception is raised. *----------------------------------------------------------------------------*/ -struct uint128 - softfloat_propagateNaNExtF80UI( - uint_fast16_t uiA64, - uint_fast64_t uiA0, - uint_fast16_t uiB64, - uint_fast64_t uiB0 - ); +struct uint128 softfloat_propagateNaNExtF80UI(uint_fast16_t uiA64, uint_fast64_t uiA0, uint_fast16_t uiB64, uint_fast64_t uiB0); /*---------------------------------------------------------------------------- | The bit pattern for a default generated 128-bit floating-point NaN. *----------------------------------------------------------------------------*/ -#define defaultNaNF128UI64 UINT64_C( 0xFFFF800000000000 ) -#define defaultNaNF128UI0 UINT64_C( 0 ) +#define defaultNaNF128UI64 UINT64_C(0xFFFF800000000000) +#define defaultNaNF128UI0 UINT64_C(0) /*---------------------------------------------------------------------------- | Returns true when the 128-bit unsigned integer formed from concatenating @@ -255,7 +246,8 @@ struct uint128 | point signaling NaN. | Note: This macro evaluates its arguments more than once. *----------------------------------------------------------------------------*/ -#define softfloat_isSigNaNF128UI( uiA64, uiA0 ) ((((uiA64) & UINT64_C( 0x7FFF800000000000 )) == UINT64_C( 0x7FFF000000000000 )) && ((uiA0) || ((uiA64) & UINT64_C( 0x00007FFFFFFFFFFF )))) +#define softfloat_isSigNaNF128UI(uiA64, uiA0) \ + ((((uiA64)&UINT64_C(0x7FFF800000000000)) == UINT64_C(0x7FFF000000000000)) && ((uiA0) || ((uiA64)&UINT64_C(0x00007FFFFFFFFFFF)))) /*---------------------------------------------------------------------------- | Assuming the unsigned integer formed from concatenating 'uiA64' and 'uiA0' @@ -264,15 +256,13 @@ struct uint128 | pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid exception | is raised. *----------------------------------------------------------------------------*/ -void - softfloat_f128UIToCommonNaN( - uint_fast64_t uiA64, uint_fast64_t uiA0, struct commonNaN *zPtr ); +void softfloat_f128UIToCommonNaN(uint_fast64_t uiA64, uint_fast64_t uiA0, struct commonNaN* zPtr); /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by 'aPtr' into a 128-bit floating-point | NaN, and returns the bit pattern of this value as an unsigned integer. *----------------------------------------------------------------------------*/ -struct uint128 softfloat_commonNaNToF128UI( const struct commonNaN * ); +struct uint128 softfloat_commonNaNToF128UI(const struct commonNaN*); /*---------------------------------------------------------------------------- | Interpreting the unsigned integer formed from concatenating 'uiA64' and @@ -283,13 +273,7 @@ struct uint128 softfloat_commonNaNToF128UI( const struct commonNaN * ); | If either original floating-point value is a signaling NaN, the invalid | exception is raised. *----------------------------------------------------------------------------*/ -struct uint128 - softfloat_propagateNaNF128UI( - uint_fast64_t uiA64, - uint_fast64_t uiA0, - uint_fast64_t uiB64, - uint_fast64_t uiB0 - ); +struct uint128 softfloat_propagateNaNF128UI(uint_fast64_t uiA64, uint_fast64_t uiA0, uint_fast64_t uiB64, uint_fast64_t uiB0); #else @@ -304,18 +288,14 @@ struct uint128 | common NaN at the location pointed to by 'zPtr'. If the NaN is a signaling | NaN, the invalid exception is raised. *----------------------------------------------------------------------------*/ -void - softfloat_extF80MToCommonNaN( - const struct extFloat80M *aSPtr, struct commonNaN *zPtr ); +void softfloat_extF80MToCommonNaN(const struct extFloat80M* aSPtr, struct commonNaN* zPtr); /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by 'aPtr' into an 80-bit extended | floating-point NaN, and stores this NaN at the location pointed to by | 'zSPtr'. *----------------------------------------------------------------------------*/ -void - softfloat_commonNaNToExtF80M( - const struct commonNaN *aPtr, struct extFloat80M *zSPtr ); +void softfloat_commonNaNToExtF80M(const struct commonNaN* aPtr, struct extFloat80M* zSPtr); /*---------------------------------------------------------------------------- | Assuming at least one of the two 80-bit extended floating-point values @@ -323,12 +303,7 @@ void | at the location pointed to by 'zSPtr'. If either original floating-point | value is a signaling NaN, the invalid exception is raised. *----------------------------------------------------------------------------*/ -void - softfloat_propagateNaNExtF80M( - const struct extFloat80M *aSPtr, - const struct extFloat80M *bSPtr, - struct extFloat80M *zSPtr - ); +void softfloat_propagateNaNExtF80M(const struct extFloat80M* aSPtr, const struct extFloat80M* bSPtr, struct extFloat80M* zSPtr); /*---------------------------------------------------------------------------- | The bit pattern for a default generated 128-bit floating-point NaN. @@ -336,7 +311,7 @@ void #define defaultNaNF128UI96 0xFFFF8000 #define defaultNaNF128UI64 0 #define defaultNaNF128UI32 0 -#define defaultNaNF128UI0 0 +#define defaultNaNF128UI0 0 /*---------------------------------------------------------------------------- | Assuming the 128-bit floating-point value pointed to by 'aWPtr' is a NaN, @@ -346,8 +321,7 @@ void | four 32-bit elements that concatenate in the platform's normal endian order | to form a 128-bit floating-point value. *----------------------------------------------------------------------------*/ -void - softfloat_f128MToCommonNaN( const uint32_t *aWPtr, struct commonNaN *zPtr ); +void softfloat_f128MToCommonNaN(const uint32_t* aWPtr, struct commonNaN* zPtr); /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by 'aPtr' into a 128-bit floating-point @@ -355,8 +329,7 @@ void | 'zWPtr' points to an array of four 32-bit elements that concatenate in the | platform's normal endian order to form a 128-bit floating-point value. *----------------------------------------------------------------------------*/ -void - softfloat_commonNaNToF128M( const struct commonNaN *aPtr, uint32_t *zWPtr ); +void softfloat_commonNaNToF128M(const struct commonNaN* aPtr, uint32_t* zWPtr); /*---------------------------------------------------------------------------- | Assuming at least one of the two 128-bit floating-point values pointed to by @@ -366,11 +339,8 @@ void | and 'zWPtr' points to an array of four 32-bit elements that concatenate in | the platform's normal endian order to form a 128-bit floating-point value. *----------------------------------------------------------------------------*/ -void - softfloat_propagateNaNF128M( - const uint32_t *aWPtr, const uint32_t *bWPtr, uint32_t *zWPtr ); +void softfloat_propagateNaNF128M(const uint32_t* aWPtr, const uint32_t* bWPtr, uint32_t* zWPtr); #endif #endif - diff --git a/softfloat/source/8086/specialize.h b/softfloat/source/8086/specialize.h index 5fe119a..23b1632 100644 --- a/softfloat/source/8086/specialize.h +++ b/softfloat/source/8086/specialize.h @@ -37,10 +37,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef specialize_h #define specialize_h 1 -#include -#include #include "primitiveTypes.h" #include "softfloat.h" +#include +#include /*---------------------------------------------------------------------------- | Default value for 'softfloat_detectTininess'. @@ -53,21 +53,21 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *----------------------------------------------------------------------------*/ #define ui32_fromPosOverflow 0xFFFFFFFF #define ui32_fromNegOverflow 0xFFFFFFFF -#define ui32_fromNaN 0xFFFFFFFF -#define i32_fromPosOverflow (-0x7FFFFFFF - 1) -#define i32_fromNegOverflow (-0x7FFFFFFF - 1) -#define i32_fromNaN (-0x7FFFFFFF - 1) +#define ui32_fromNaN 0xFFFFFFFF +#define i32_fromPosOverflow (-0x7FFFFFFF - 1) +#define i32_fromNegOverflow (-0x7FFFFFFF - 1) +#define i32_fromNaN (-0x7FFFFFFF - 1) /*---------------------------------------------------------------------------- | The values to return on conversions to 64-bit integer formats that raise an | invalid exception. *----------------------------------------------------------------------------*/ -#define ui64_fromPosOverflow UINT64_C( 0xFFFFFFFFFFFFFFFF ) -#define ui64_fromNegOverflow UINT64_C( 0xFFFFFFFFFFFFFFFF ) -#define ui64_fromNaN UINT64_C( 0xFFFFFFFFFFFFFFFF ) -#define i64_fromPosOverflow (-INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1) -#define i64_fromNegOverflow (-INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1) -#define i64_fromNaN (-INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1) +#define ui64_fromPosOverflow UINT64_C(0xFFFFFFFFFFFFFFFF) +#define ui64_fromNegOverflow UINT64_C(0xFFFFFFFFFFFFFFFF) +#define ui64_fromNaN UINT64_C(0xFFFFFFFFFFFFFFFF) +#define i64_fromPosOverflow (-INT64_C(0x7FFFFFFFFFFFFFFF) - 1) +#define i64_fromNegOverflow (-INT64_C(0x7FFFFFFFFFFFFFFF) - 1) +#define i64_fromNaN (-INT64_C(0x7FFFFFFFFFFFFFFF) - 1) /*---------------------------------------------------------------------------- | "Common NaN" structure, used to transfer NaN representations from one format @@ -92,7 +92,7 @@ struct commonNaN { | 16-bit floating-point signaling NaN. | Note: This macro evaluates its argument more than once. *----------------------------------------------------------------------------*/ -#define softfloat_isSigNaNF16UI( uiA ) ((((uiA) & 0x7E00) == 0x7C00) && ((uiA) & 0x01FF)) +#define softfloat_isSigNaNF16UI(uiA) ((((uiA)&0x7E00) == 0x7C00) && ((uiA)&0x01FF)) /*---------------------------------------------------------------------------- | Assuming 'uiA' has the bit pattern of a 16-bit floating-point NaN, converts @@ -100,13 +100,13 @@ struct commonNaN { | location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid | exception is raised. *----------------------------------------------------------------------------*/ -void softfloat_f16UIToCommonNaN( uint_fast16_t uiA, struct commonNaN *zPtr ); +void softfloat_f16UIToCommonNaN(uint_fast16_t uiA, struct commonNaN* zPtr); /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by 'aPtr' into a 16-bit floating-point | NaN, and returns the bit pattern of this value as an unsigned integer. *----------------------------------------------------------------------------*/ -uint_fast16_t softfloat_commonNaNToF16UI( const struct commonNaN *aPtr ); +uint_fast16_t softfloat_commonNaNToF16UI(const struct commonNaN* aPtr); /*---------------------------------------------------------------------------- | Interpreting 'uiA' and 'uiB' as the bit patterns of two 16-bit floating- @@ -114,8 +114,7 @@ uint_fast16_t softfloat_commonNaNToF16UI( const struct commonNaN *aPtr ); | the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a | signaling NaN, the invalid exception is raised. *----------------------------------------------------------------------------*/ -uint_fast16_t - softfloat_propagateNaNF16UI( uint_fast16_t uiA, uint_fast16_t uiB ); +uint_fast16_t softfloat_propagateNaNF16UI(uint_fast16_t uiA, uint_fast16_t uiB); /*---------------------------------------------------------------------------- | The bit pattern for a default generated 32-bit floating-point NaN. @@ -127,7 +126,7 @@ uint_fast16_t | 32-bit floating-point signaling NaN. | Note: This macro evaluates its argument more than once. *----------------------------------------------------------------------------*/ -#define softfloat_isSigNaNF32UI( uiA ) ((((uiA) & 0x7FC00000) == 0x7F800000) && ((uiA) & 0x003FFFFF)) +#define softfloat_isSigNaNF32UI(uiA) ((((uiA)&0x7FC00000) == 0x7F800000) && ((uiA)&0x003FFFFF)) /*---------------------------------------------------------------------------- | Assuming 'uiA' has the bit pattern of a 32-bit floating-point NaN, converts @@ -135,13 +134,13 @@ uint_fast16_t | location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid | exception is raised. *----------------------------------------------------------------------------*/ -void softfloat_f32UIToCommonNaN( uint_fast32_t uiA, struct commonNaN *zPtr ); +void softfloat_f32UIToCommonNaN(uint_fast32_t uiA, struct commonNaN* zPtr); /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by 'aPtr' into a 32-bit floating-point | NaN, and returns the bit pattern of this value as an unsigned integer. *----------------------------------------------------------------------------*/ -uint_fast32_t softfloat_commonNaNToF32UI( const struct commonNaN *aPtr ); +uint_fast32_t softfloat_commonNaNToF32UI(const struct commonNaN* aPtr); /*---------------------------------------------------------------------------- | Interpreting 'uiA' and 'uiB' as the bit patterns of two 32-bit floating- @@ -149,20 +148,20 @@ uint_fast32_t softfloat_commonNaNToF32UI( const struct commonNaN *aPtr ); | the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a | signaling NaN, the invalid exception is raised. *----------------------------------------------------------------------------*/ -uint_fast32_t - softfloat_propagateNaNF32UI( uint_fast32_t uiA, uint_fast32_t uiB ); +uint_fast32_t softfloat_propagateNaNF32UI(uint_fast32_t uiA, uint_fast32_t uiB); /*---------------------------------------------------------------------------- | The bit pattern for a default generated 64-bit floating-point NaN. *----------------------------------------------------------------------------*/ -#define defaultNaNF64UI UINT64_C( 0xFFF8000000000000 ) +#define defaultNaNF64UI UINT64_C(0xFFF8000000000000) /*---------------------------------------------------------------------------- | Returns true when 64-bit unsigned integer 'uiA' has the bit pattern of a | 64-bit floating-point signaling NaN. | Note: This macro evaluates its argument more than once. *----------------------------------------------------------------------------*/ -#define softfloat_isSigNaNF64UI( uiA ) ((((uiA) & UINT64_C( 0x7FF8000000000000 )) == UINT64_C( 0x7FF0000000000000 )) && ((uiA) & UINT64_C( 0x0007FFFFFFFFFFFF ))) +#define softfloat_isSigNaNF64UI(uiA) \ + ((((uiA)&UINT64_C(0x7FF8000000000000)) == UINT64_C(0x7FF0000000000000)) && ((uiA)&UINT64_C(0x0007FFFFFFFFFFFF))) /*---------------------------------------------------------------------------- | Assuming 'uiA' has the bit pattern of a 64-bit floating-point NaN, converts @@ -170,13 +169,13 @@ uint_fast32_t | location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid | exception is raised. *----------------------------------------------------------------------------*/ -void softfloat_f64UIToCommonNaN( uint_fast64_t uiA, struct commonNaN *zPtr ); +void softfloat_f64UIToCommonNaN(uint_fast64_t uiA, struct commonNaN* zPtr); /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by 'aPtr' into a 64-bit floating-point | NaN, and returns the bit pattern of this value as an unsigned integer. *----------------------------------------------------------------------------*/ -uint_fast64_t softfloat_commonNaNToF64UI( const struct commonNaN *aPtr ); +uint_fast64_t softfloat_commonNaNToF64UI(const struct commonNaN* aPtr); /*---------------------------------------------------------------------------- | Interpreting 'uiA' and 'uiB' as the bit patterns of two 64-bit floating- @@ -184,14 +183,13 @@ uint_fast64_t softfloat_commonNaNToF64UI( const struct commonNaN *aPtr ); | the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a | signaling NaN, the invalid exception is raised. *----------------------------------------------------------------------------*/ -uint_fast64_t - softfloat_propagateNaNF64UI( uint_fast64_t uiA, uint_fast64_t uiB ); +uint_fast64_t softfloat_propagateNaNF64UI(uint_fast64_t uiA, uint_fast64_t uiB); /*---------------------------------------------------------------------------- | The bit pattern for a default generated 80-bit extended floating-point NaN. *----------------------------------------------------------------------------*/ #define defaultNaNExtF80UI64 0xFFFF -#define defaultNaNExtF80UI0 UINT64_C( 0xC000000000000000 ) +#define defaultNaNExtF80UI0 UINT64_C(0xC000000000000000) /*---------------------------------------------------------------------------- | Returns true when the 80-bit unsigned integer formed from concatenating @@ -199,7 +197,8 @@ uint_fast64_t | floating-point signaling NaN. | Note: This macro evaluates its arguments more than once. *----------------------------------------------------------------------------*/ -#define softfloat_isSigNaNExtF80UI( uiA64, uiA0 ) ((((uiA64) & 0x7FFF) == 0x7FFF) && ! ((uiA0) & UINT64_C( 0x4000000000000000 )) && ((uiA0) & UINT64_C( 0x3FFFFFFFFFFFFFFF ))) +#define softfloat_isSigNaNExtF80UI(uiA64, uiA0) \ + ((((uiA64)&0x7FFF) == 0x7FFF) && !((uiA0)&UINT64_C(0x4000000000000000)) && ((uiA0)&UINT64_C(0x3FFFFFFFFFFFFFFF))) #ifdef SOFTFLOAT_FAST_INT64 @@ -215,16 +214,14 @@ uint_fast64_t | location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid | exception is raised. *----------------------------------------------------------------------------*/ -void - softfloat_extF80UIToCommonNaN( - uint_fast16_t uiA64, uint_fast64_t uiA0, struct commonNaN *zPtr ); +void softfloat_extF80UIToCommonNaN(uint_fast16_t uiA64, uint_fast64_t uiA0, struct commonNaN* zPtr); /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by 'aPtr' into an 80-bit extended | floating-point NaN, and returns the bit pattern of this value as an unsigned | integer. *----------------------------------------------------------------------------*/ -struct uint128 softfloat_commonNaNToExtF80UI( const struct commonNaN *aPtr ); +struct uint128 softfloat_commonNaNToExtF80UI(const struct commonNaN* aPtr); /*---------------------------------------------------------------------------- | Interpreting the unsigned integer formed from concatenating 'uiA64' and @@ -235,19 +232,13 @@ struct uint128 softfloat_commonNaNToExtF80UI( const struct commonNaN *aPtr ); | result. If either original floating-point value is a signaling NaN, the | invalid exception is raised. *----------------------------------------------------------------------------*/ -struct uint128 - softfloat_propagateNaNExtF80UI( - uint_fast16_t uiA64, - uint_fast64_t uiA0, - uint_fast16_t uiB64, - uint_fast64_t uiB0 - ); +struct uint128 softfloat_propagateNaNExtF80UI(uint_fast16_t uiA64, uint_fast64_t uiA0, uint_fast16_t uiB64, uint_fast64_t uiB0); /*---------------------------------------------------------------------------- | The bit pattern for a default generated 128-bit floating-point NaN. *----------------------------------------------------------------------------*/ -#define defaultNaNF128UI64 UINT64_C( 0xFFFF800000000000 ) -#define defaultNaNF128UI0 UINT64_C( 0 ) +#define defaultNaNF128UI64 UINT64_C(0xFFFF800000000000) +#define defaultNaNF128UI0 UINT64_C(0) /*---------------------------------------------------------------------------- | Returns true when the 128-bit unsigned integer formed from concatenating @@ -255,7 +246,8 @@ struct uint128 | point signaling NaN. | Note: This macro evaluates its arguments more than once. *----------------------------------------------------------------------------*/ -#define softfloat_isSigNaNF128UI( uiA64, uiA0 ) ((((uiA64) & UINT64_C( 0x7FFF800000000000 )) == UINT64_C( 0x7FFF000000000000 )) && ((uiA0) || ((uiA64) & UINT64_C( 0x00007FFFFFFFFFFF )))) +#define softfloat_isSigNaNF128UI(uiA64, uiA0) \ + ((((uiA64)&UINT64_C(0x7FFF800000000000)) == UINT64_C(0x7FFF000000000000)) && ((uiA0) || ((uiA64)&UINT64_C(0x00007FFFFFFFFFFF)))) /*---------------------------------------------------------------------------- | Assuming the unsigned integer formed from concatenating 'uiA64' and 'uiA0' @@ -264,15 +256,13 @@ struct uint128 | pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid exception | is raised. *----------------------------------------------------------------------------*/ -void - softfloat_f128UIToCommonNaN( - uint_fast64_t uiA64, uint_fast64_t uiA0, struct commonNaN *zPtr ); +void softfloat_f128UIToCommonNaN(uint_fast64_t uiA64, uint_fast64_t uiA0, struct commonNaN* zPtr); /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by 'aPtr' into a 128-bit floating-point | NaN, and returns the bit pattern of this value as an unsigned integer. *----------------------------------------------------------------------------*/ -struct uint128 softfloat_commonNaNToF128UI( const struct commonNaN * ); +struct uint128 softfloat_commonNaNToF128UI(const struct commonNaN*); /*---------------------------------------------------------------------------- | Interpreting the unsigned integer formed from concatenating 'uiA64' and @@ -283,13 +273,7 @@ struct uint128 softfloat_commonNaNToF128UI( const struct commonNaN * ); | If either original floating-point value is a signaling NaN, the invalid | exception is raised. *----------------------------------------------------------------------------*/ -struct uint128 - softfloat_propagateNaNF128UI( - uint_fast64_t uiA64, - uint_fast64_t uiA0, - uint_fast64_t uiB64, - uint_fast64_t uiB0 - ); +struct uint128 softfloat_propagateNaNF128UI(uint_fast64_t uiA64, uint_fast64_t uiA0, uint_fast64_t uiB64, uint_fast64_t uiB0); #else @@ -304,18 +288,14 @@ struct uint128 | common NaN at the location pointed to by 'zPtr'. If the NaN is a signaling | NaN, the invalid exception is raised. *----------------------------------------------------------------------------*/ -void - softfloat_extF80MToCommonNaN( - const struct extFloat80M *aSPtr, struct commonNaN *zPtr ); +void softfloat_extF80MToCommonNaN(const struct extFloat80M* aSPtr, struct commonNaN* zPtr); /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by 'aPtr' into an 80-bit extended | floating-point NaN, and stores this NaN at the location pointed to by | 'zSPtr'. *----------------------------------------------------------------------------*/ -void - softfloat_commonNaNToExtF80M( - const struct commonNaN *aPtr, struct extFloat80M *zSPtr ); +void softfloat_commonNaNToExtF80M(const struct commonNaN* aPtr, struct extFloat80M* zSPtr); /*---------------------------------------------------------------------------- | Assuming at least one of the two 80-bit extended floating-point values @@ -323,12 +303,7 @@ void | at the location pointed to by 'zSPtr'. If either original floating-point | value is a signaling NaN, the invalid exception is raised. *----------------------------------------------------------------------------*/ -void - softfloat_propagateNaNExtF80M( - const struct extFloat80M *aSPtr, - const struct extFloat80M *bSPtr, - struct extFloat80M *zSPtr - ); +void softfloat_propagateNaNExtF80M(const struct extFloat80M* aSPtr, const struct extFloat80M* bSPtr, struct extFloat80M* zSPtr); /*---------------------------------------------------------------------------- | The bit pattern for a default generated 128-bit floating-point NaN. @@ -336,7 +311,7 @@ void #define defaultNaNF128UI96 0xFFFF8000 #define defaultNaNF128UI64 0 #define defaultNaNF128UI32 0 -#define defaultNaNF128UI0 0 +#define defaultNaNF128UI0 0 /*---------------------------------------------------------------------------- | Assuming the 128-bit floating-point value pointed to by 'aWPtr' is a NaN, @@ -346,8 +321,7 @@ void | four 32-bit elements that concatenate in the platform's normal endian order | to form a 128-bit floating-point value. *----------------------------------------------------------------------------*/ -void - softfloat_f128MToCommonNaN( const uint32_t *aWPtr, struct commonNaN *zPtr ); +void softfloat_f128MToCommonNaN(const uint32_t* aWPtr, struct commonNaN* zPtr); /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by 'aPtr' into a 128-bit floating-point @@ -355,8 +329,7 @@ void | 'zWPtr' points to an array of four 32-bit elements that concatenate in the | platform's normal endian order to form a 128-bit floating-point value. *----------------------------------------------------------------------------*/ -void - softfloat_commonNaNToF128M( const struct commonNaN *aPtr, uint32_t *zWPtr ); +void softfloat_commonNaNToF128M(const struct commonNaN* aPtr, uint32_t* zWPtr); /*---------------------------------------------------------------------------- | Assuming at least one of the two 128-bit floating-point values pointed to by @@ -366,11 +339,8 @@ void | and 'zWPtr' points to an array of four 32-bit elements that concatenate in | the platform's normal endian order to form a 128-bit floating-point value. *----------------------------------------------------------------------------*/ -void - softfloat_propagateNaNF128M( - const uint32_t *aWPtr, const uint32_t *bWPtr, uint32_t *zWPtr ); +void softfloat_propagateNaNF128M(const uint32_t* aWPtr, const uint32_t* bWPtr, uint32_t* zWPtr); #endif #endif - diff --git a/softfloat/source/ARM-VFPv2-defaultNaN/specialize.h b/softfloat/source/ARM-VFPv2-defaultNaN/specialize.h index 2c481a2..9d8e569 100644 --- a/softfloat/source/ARM-VFPv2-defaultNaN/specialize.h +++ b/softfloat/source/ARM-VFPv2-defaultNaN/specialize.h @@ -37,10 +37,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef specialize_h #define specialize_h 1 -#include -#include #include "primitiveTypes.h" #include "softfloat.h" +#include +#include /*---------------------------------------------------------------------------- | Default value for 'softfloat_detectTininess'. @@ -53,27 +53,29 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *----------------------------------------------------------------------------*/ #define ui32_fromPosOverflow 0xFFFFFFFF #define ui32_fromNegOverflow 0 -#define ui32_fromNaN 0 -#define i32_fromPosOverflow 0x7FFFFFFF -#define i32_fromNegOverflow (-0x7FFFFFFF - 1) -#define i32_fromNaN 0 +#define ui32_fromNaN 0 +#define i32_fromPosOverflow 0x7FFFFFFF +#define i32_fromNegOverflow (-0x7FFFFFFF - 1) +#define i32_fromNaN 0 /*---------------------------------------------------------------------------- | The values to return on conversions to 64-bit integer formats that raise an | invalid exception. *----------------------------------------------------------------------------*/ -#define ui64_fromPosOverflow UINT64_C( 0xFFFFFFFFFFFFFFFF ) +#define ui64_fromPosOverflow UINT64_C(0xFFFFFFFFFFFFFFFF) #define ui64_fromNegOverflow 0 -#define ui64_fromNaN 0 -#define i64_fromPosOverflow INT64_C( 0x7FFFFFFFFFFFFFFF ) -#define i64_fromNegOverflow (-INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1) -#define i64_fromNaN 0 +#define ui64_fromNaN 0 +#define i64_fromPosOverflow INT64_C(0x7FFFFFFFFFFFFFFF) +#define i64_fromNegOverflow (-INT64_C(0x7FFFFFFFFFFFFFFF) - 1) +#define i64_fromNaN 0 /*---------------------------------------------------------------------------- | "Common NaN" structure, used to transfer NaN representations from one format | to another. *----------------------------------------------------------------------------*/ -struct commonNaN { char _unused; }; +struct commonNaN { + char _unused; +}; /*---------------------------------------------------------------------------- | The bit pattern for a default generated 16-bit floating-point NaN. @@ -85,7 +87,7 @@ struct commonNaN { char _unused; }; | 16-bit floating-point signaling NaN. | Note: This macro evaluates its argument more than once. *----------------------------------------------------------------------------*/ -#define softfloat_isSigNaNF16UI( uiA ) ((((uiA) & 0x7E00) == 0x7C00) && ((uiA) & 0x01FF)) +#define softfloat_isSigNaNF16UI(uiA) ((((uiA)&0x7E00) == 0x7C00) && ((uiA)&0x01FF)) /*---------------------------------------------------------------------------- | Assuming 'uiA' has the bit pattern of a 16-bit floating-point NaN, converts @@ -93,13 +95,15 @@ struct commonNaN { char _unused; }; | location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid | exception is raised. *----------------------------------------------------------------------------*/ -#define softfloat_f16UIToCommonNaN( uiA, zPtr ) if ( ! ((uiA) & 0x0200) ) softfloat_raiseFlags( softfloat_flag_invalid ) +#define softfloat_f16UIToCommonNaN(uiA, zPtr) \ + if(!((uiA)&0x0200)) \ + softfloat_raiseFlags(softfloat_flag_invalid) /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by 'aPtr' into a 16-bit floating-point | NaN, and returns the bit pattern of this value as an unsigned integer. *----------------------------------------------------------------------------*/ -#define softfloat_commonNaNToF16UI( aPtr ) ((uint_fast16_t) defaultNaNF16UI) +#define softfloat_commonNaNToF16UI(aPtr) ((uint_fast16_t)defaultNaNF16UI) /*---------------------------------------------------------------------------- | Interpreting 'uiA' and 'uiB' as the bit patterns of two 16-bit floating- @@ -107,8 +111,7 @@ struct commonNaN { char _unused; }; | the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a | signaling NaN, the invalid exception is raised. *----------------------------------------------------------------------------*/ -uint_fast16_t - softfloat_propagateNaNF16UI( uint_fast16_t uiA, uint_fast16_t uiB ); +uint_fast16_t softfloat_propagateNaNF16UI(uint_fast16_t uiA, uint_fast16_t uiB); /*---------------------------------------------------------------------------- | The bit pattern for a default generated 32-bit floating-point NaN. @@ -120,7 +123,7 @@ uint_fast16_t | 32-bit floating-point signaling NaN. | Note: This macro evaluates its argument more than once. *----------------------------------------------------------------------------*/ -#define softfloat_isSigNaNF32UI( uiA ) ((((uiA) & 0x7FC00000) == 0x7F800000) && ((uiA) & 0x003FFFFF)) +#define softfloat_isSigNaNF32UI(uiA) ((((uiA)&0x7FC00000) == 0x7F800000) && ((uiA)&0x003FFFFF)) /*---------------------------------------------------------------------------- | Assuming 'uiA' has the bit pattern of a 32-bit floating-point NaN, converts @@ -128,13 +131,15 @@ uint_fast16_t | location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid | exception is raised. *----------------------------------------------------------------------------*/ -#define softfloat_f32UIToCommonNaN( uiA, zPtr ) if ( ! ((uiA) & 0x00400000) ) softfloat_raiseFlags( softfloat_flag_invalid ) +#define softfloat_f32UIToCommonNaN(uiA, zPtr) \ + if(!((uiA)&0x00400000)) \ + softfloat_raiseFlags(softfloat_flag_invalid) /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by 'aPtr' into a 32-bit floating-point | NaN, and returns the bit pattern of this value as an unsigned integer. *----------------------------------------------------------------------------*/ -#define softfloat_commonNaNToF32UI( aPtr ) ((uint_fast32_t) defaultNaNF32UI) +#define softfloat_commonNaNToF32UI(aPtr) ((uint_fast32_t)defaultNaNF32UI) /*---------------------------------------------------------------------------- | Interpreting 'uiA' and 'uiB' as the bit patterns of two 32-bit floating- @@ -142,20 +147,20 @@ uint_fast16_t | the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a | signaling NaN, the invalid exception is raised. *----------------------------------------------------------------------------*/ -uint_fast32_t - softfloat_propagateNaNF32UI( uint_fast32_t uiA, uint_fast32_t uiB ); +uint_fast32_t softfloat_propagateNaNF32UI(uint_fast32_t uiA, uint_fast32_t uiB); /*---------------------------------------------------------------------------- | The bit pattern for a default generated 64-bit floating-point NaN. *----------------------------------------------------------------------------*/ -#define defaultNaNF64UI UINT64_C( 0x7FF8000000000000 ) +#define defaultNaNF64UI UINT64_C(0x7FF8000000000000) /*---------------------------------------------------------------------------- | Returns true when 64-bit unsigned integer 'uiA' has the bit pattern of a | 64-bit floating-point signaling NaN. | Note: This macro evaluates its argument more than once. *----------------------------------------------------------------------------*/ -#define softfloat_isSigNaNF64UI( uiA ) ((((uiA) & UINT64_C( 0x7FF8000000000000 )) == UINT64_C( 0x7FF0000000000000 )) && ((uiA) & UINT64_C( 0x0007FFFFFFFFFFFF ))) +#define softfloat_isSigNaNF64UI(uiA) \ + ((((uiA)&UINT64_C(0x7FF8000000000000)) == UINT64_C(0x7FF0000000000000)) && ((uiA)&UINT64_C(0x0007FFFFFFFFFFFF))) /*---------------------------------------------------------------------------- | Assuming 'uiA' has the bit pattern of a 64-bit floating-point NaN, converts @@ -163,13 +168,15 @@ uint_fast32_t | location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid | exception is raised. *----------------------------------------------------------------------------*/ -#define softfloat_f64UIToCommonNaN( uiA, zPtr ) if ( ! ((uiA) & UINT64_C( 0x0008000000000000 )) ) softfloat_raiseFlags( softfloat_flag_invalid ) +#define softfloat_f64UIToCommonNaN(uiA, zPtr) \ + if(!((uiA)&UINT64_C(0x0008000000000000))) \ + softfloat_raiseFlags(softfloat_flag_invalid) /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by 'aPtr' into a 64-bit floating-point | NaN, and returns the bit pattern of this value as an unsigned integer. *----------------------------------------------------------------------------*/ -#define softfloat_commonNaNToF64UI( aPtr ) ((uint_fast64_t) defaultNaNF64UI) +#define softfloat_commonNaNToF64UI(aPtr) ((uint_fast64_t)defaultNaNF64UI) /*---------------------------------------------------------------------------- | Interpreting 'uiA' and 'uiB' as the bit patterns of two 64-bit floating- @@ -177,14 +184,13 @@ uint_fast32_t | the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a | signaling NaN, the invalid exception is raised. *----------------------------------------------------------------------------*/ -uint_fast64_t - softfloat_propagateNaNF64UI( uint_fast64_t uiA, uint_fast64_t uiB ); +uint_fast64_t softfloat_propagateNaNF64UI(uint_fast64_t uiA, uint_fast64_t uiB); /*---------------------------------------------------------------------------- | The bit pattern for a default generated 80-bit extended floating-point NaN. *----------------------------------------------------------------------------*/ #define defaultNaNExtF80UI64 0x7FFF -#define defaultNaNExtF80UI0 UINT64_C( 0xC000000000000000 ) +#define defaultNaNExtF80UI0 UINT64_C(0xC000000000000000) /*---------------------------------------------------------------------------- | Returns true when the 80-bit unsigned integer formed from concatenating @@ -192,7 +198,8 @@ uint_fast64_t | floating-point signaling NaN. | Note: This macro evaluates its arguments more than once. *----------------------------------------------------------------------------*/ -#define softfloat_isSigNaNExtF80UI( uiA64, uiA0 ) ((((uiA64) & 0x7FFF) == 0x7FFF) && ! ((uiA0) & UINT64_C( 0x4000000000000000 )) && ((uiA0) & UINT64_C( 0x3FFFFFFFFFFFFFFF ))) +#define softfloat_isSigNaNExtF80UI(uiA64, uiA0) \ + ((((uiA64)&0x7FFF) == 0x7FFF) && !((uiA0)&UINT64_C(0x4000000000000000)) && ((uiA0)&UINT64_C(0x3FFFFFFFFFFFFFFF))) #ifdef SOFTFLOAT_FAST_INT64 @@ -208,24 +215,25 @@ uint_fast64_t | location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid | exception is raised. *----------------------------------------------------------------------------*/ -#define softfloat_extF80UIToCommonNaN( uiA64, uiA0, zPtr ) if ( ! ((uiA0) & UINT64_C( 0x4000000000000000 )) ) softfloat_raiseFlags( softfloat_flag_invalid ) +#define softfloat_extF80UIToCommonNaN(uiA64, uiA0, zPtr) \ + if(!((uiA0)&UINT64_C(0x4000000000000000))) \ + softfloat_raiseFlags(softfloat_flag_invalid) /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by 'aPtr' into an 80-bit extended | floating-point NaN, and returns the bit pattern of this value as an unsigned | integer. *----------------------------------------------------------------------------*/ -#if defined INLINE && ! defined softfloat_commonNaNToExtF80UI +#if defined INLINE && !defined softfloat_commonNaNToExtF80UI INLINE -struct uint128 softfloat_commonNaNToExtF80UI( const struct commonNaN *aPtr ) -{ +struct uint128 softfloat_commonNaNToExtF80UI(const struct commonNaN* aPtr) { struct uint128 uiZ; uiZ.v64 = defaultNaNExtF80UI64; - uiZ.v0 = defaultNaNExtF80UI0; + uiZ.v0 = defaultNaNExtF80UI0; return uiZ; } #else -struct uint128 softfloat_commonNaNToExtF80UI( const struct commonNaN *aPtr ); +struct uint128 softfloat_commonNaNToExtF80UI(const struct commonNaN* aPtr); #endif /*---------------------------------------------------------------------------- @@ -237,19 +245,13 @@ struct uint128 softfloat_commonNaNToExtF80UI( const struct commonNaN *aPtr ); | result. If either original floating-point value is a signaling NaN, the | invalid exception is raised. *----------------------------------------------------------------------------*/ -struct uint128 - softfloat_propagateNaNExtF80UI( - uint_fast16_t uiA64, - uint_fast64_t uiA0, - uint_fast16_t uiB64, - uint_fast64_t uiB0 - ); +struct uint128 softfloat_propagateNaNExtF80UI(uint_fast16_t uiA64, uint_fast64_t uiA0, uint_fast16_t uiB64, uint_fast64_t uiB0); /*---------------------------------------------------------------------------- | The bit pattern for a default generated 128-bit floating-point NaN. *----------------------------------------------------------------------------*/ -#define defaultNaNF128UI64 UINT64_C( 0x7FFF800000000000 ) -#define defaultNaNF128UI0 UINT64_C( 0 ) +#define defaultNaNF128UI64 UINT64_C(0x7FFF800000000000) +#define defaultNaNF128UI0 UINT64_C(0) /*---------------------------------------------------------------------------- | Returns true when the 128-bit unsigned integer formed from concatenating @@ -257,7 +259,8 @@ struct uint128 | point signaling NaN. | Note: This macro evaluates its arguments more than once. *----------------------------------------------------------------------------*/ -#define softfloat_isSigNaNF128UI( uiA64, uiA0 ) ((((uiA64) & UINT64_C( 0x7FFF800000000000 )) == UINT64_C( 0x7FFF000000000000 )) && ((uiA0) || ((uiA64) & UINT64_C( 0x00007FFFFFFFFFFF )))) +#define softfloat_isSigNaNF128UI(uiA64, uiA0) \ + ((((uiA64)&UINT64_C(0x7FFF800000000000)) == UINT64_C(0x7FFF000000000000)) && ((uiA0) || ((uiA64)&UINT64_C(0x00007FFFFFFFFFFF)))) /*---------------------------------------------------------------------------- | Assuming the unsigned integer formed from concatenating 'uiA64' and 'uiA0' @@ -266,23 +269,24 @@ struct uint128 | pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid exception | is raised. *----------------------------------------------------------------------------*/ -#define softfloat_f128UIToCommonNaN( uiA64, uiA0, zPtr ) if ( ! ((uiA64) & UINT64_C( 0x0000800000000000 )) ) softfloat_raiseFlags( softfloat_flag_invalid ) +#define softfloat_f128UIToCommonNaN(uiA64, uiA0, zPtr) \ + if(!((uiA64)&UINT64_C(0x0000800000000000))) \ + softfloat_raiseFlags(softfloat_flag_invalid) /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by 'aPtr' into a 128-bit floating-point | NaN, and returns the bit pattern of this value as an unsigned integer. *----------------------------------------------------------------------------*/ -#if defined INLINE && ! defined softfloat_commonNaNToF128UI +#if defined INLINE && !defined softfloat_commonNaNToF128UI INLINE -struct uint128 softfloat_commonNaNToF128UI( const struct commonNaN *aPtr ) -{ +struct uint128 softfloat_commonNaNToF128UI(const struct commonNaN* aPtr) { struct uint128 uiZ; uiZ.v64 = defaultNaNF128UI64; - uiZ.v0 = defaultNaNF128UI0; + uiZ.v0 = defaultNaNF128UI0; return uiZ; } #else -struct uint128 softfloat_commonNaNToF128UI( const struct commonNaN * ); +struct uint128 softfloat_commonNaNToF128UI(const struct commonNaN*); #endif /*---------------------------------------------------------------------------- @@ -294,13 +298,7 @@ struct uint128 softfloat_commonNaNToF128UI( const struct commonNaN * ); | If either original floating-point value is a signaling NaN, the invalid | exception is raised. *----------------------------------------------------------------------------*/ -struct uint128 - softfloat_propagateNaNF128UI( - uint_fast64_t uiA64, - uint_fast64_t uiA0, - uint_fast64_t uiB64, - uint_fast64_t uiB0 - ); +struct uint128 softfloat_propagateNaNF128UI(uint_fast64_t uiA64, uint_fast64_t uiA0, uint_fast64_t uiB64, uint_fast64_t uiB0); #else @@ -315,26 +313,23 @@ struct uint128 | common NaN at the location pointed to by 'zPtr'. If the NaN is a signaling | NaN, the invalid exception is raised. *----------------------------------------------------------------------------*/ -#define softfloat_extF80MToCommonNaN( aSPtr, zPtr ) if ( ! ((aSPtr)->signif & UINT64_C( 0x4000000000000000 )) ) softfloat_raiseFlags( softfloat_flag_invalid ) +#define softfloat_extF80MToCommonNaN(aSPtr, zPtr) \ + if(!((aSPtr)->signif & UINT64_C(0x4000000000000000))) \ + softfloat_raiseFlags(softfloat_flag_invalid) /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by 'aPtr' into an 80-bit extended | floating-point NaN, and stores this NaN at the location pointed to by | 'zSPtr'. *----------------------------------------------------------------------------*/ -#if defined INLINE && ! defined softfloat_commonNaNToExtF80M +#if defined INLINE && !defined softfloat_commonNaNToExtF80M INLINE -void - softfloat_commonNaNToExtF80M( - const struct commonNaN *aPtr, struct extFloat80M *zSPtr ) -{ +void softfloat_commonNaNToExtF80M(const struct commonNaN* aPtr, struct extFloat80M* zSPtr) { zSPtr->signExp = defaultNaNExtF80UI64; - zSPtr->signif = defaultNaNExtF80UI0; + zSPtr->signif = defaultNaNExtF80UI0; } #else -void - softfloat_commonNaNToExtF80M( - const struct commonNaN *aPtr, struct extFloat80M *zSPtr ); +void softfloat_commonNaNToExtF80M(const struct commonNaN* aPtr, struct extFloat80M* zSPtr); #endif /*---------------------------------------------------------------------------- @@ -343,12 +338,7 @@ void | at the location pointed to by 'zSPtr'. If either original floating-point | value is a signaling NaN, the invalid exception is raised. *----------------------------------------------------------------------------*/ -void - softfloat_propagateNaNExtF80M( - const struct extFloat80M *aSPtr, - const struct extFloat80M *bSPtr, - struct extFloat80M *zSPtr - ); +void softfloat_propagateNaNExtF80M(const struct extFloat80M* aSPtr, const struct extFloat80M* bSPtr, struct extFloat80M* zSPtr); /*---------------------------------------------------------------------------- | The bit pattern for a default generated 128-bit floating-point NaN. @@ -356,7 +346,7 @@ void #define defaultNaNF128UI96 0x7FFF8000 #define defaultNaNF128UI64 0 #define defaultNaNF128UI32 0 -#define defaultNaNF128UI0 0 +#define defaultNaNF128UI0 0 /*---------------------------------------------------------------------------- | Assuming the 128-bit floating-point value pointed to by 'aWPtr' is a NaN, @@ -366,7 +356,9 @@ void | four 32-bit elements that concatenate in the platform's normal endian order | to form a 128-bit floating-point value. *----------------------------------------------------------------------------*/ -#define softfloat_f128MToCommonNaN( aWPtr, zPtr ) if ( ! ((aWPtr)[indexWordHi( 4 )] & UINT64_C( 0x0000800000000000 )) ) softfloat_raiseFlags( softfloat_flag_invalid ) +#define softfloat_f128MToCommonNaN(aWPtr, zPtr) \ + if(!((aWPtr)[indexWordHi(4)] & UINT64_C(0x0000800000000000))) \ + softfloat_raiseFlags(softfloat_flag_invalid) /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by 'aPtr' into a 128-bit floating-point @@ -374,19 +366,16 @@ void | 'zWPtr' points to an array of four 32-bit elements that concatenate in the | platform's normal endian order to form a 128-bit floating-point value. *----------------------------------------------------------------------------*/ -#if defined INLINE && ! defined softfloat_commonNaNToF128M +#if defined INLINE && !defined softfloat_commonNaNToF128M INLINE -void - softfloat_commonNaNToF128M( const struct commonNaN *aPtr, uint32_t *zWPtr ) -{ - zWPtr[indexWord( 4, 3 )] = defaultNaNF128UI96; - zWPtr[indexWord( 4, 2 )] = defaultNaNF128UI64; - zWPtr[indexWord( 4, 1 )] = defaultNaNF128UI32; - zWPtr[indexWord( 4, 0 )] = defaultNaNF128UI0; +void softfloat_commonNaNToF128M(const struct commonNaN* aPtr, uint32_t* zWPtr) { + zWPtr[indexWord(4, 3)] = defaultNaNF128UI96; + zWPtr[indexWord(4, 2)] = defaultNaNF128UI64; + zWPtr[indexWord(4, 1)] = defaultNaNF128UI32; + zWPtr[indexWord(4, 0)] = defaultNaNF128UI0; } #else -void - softfloat_commonNaNToF128M( const struct commonNaN *aPtr, uint32_t *zWPtr ); +void softfloat_commonNaNToF128M(const struct commonNaN* aPtr, uint32_t* zWPtr); #endif /*---------------------------------------------------------------------------- @@ -397,11 +386,8 @@ void | and 'zWPtr' points to an array of four 32-bit elements that concatenate in | the platform's normal endian order to form a 128-bit floating-point value. *----------------------------------------------------------------------------*/ -void - softfloat_propagateNaNF128M( - const uint32_t *aWPtr, const uint32_t *bWPtr, uint32_t *zWPtr ); +void softfloat_propagateNaNF128M(const uint32_t* aWPtr, const uint32_t* bWPtr, uint32_t* zWPtr); #endif #endif - diff --git a/softfloat/source/ARM-VFPv2/specialize.h b/softfloat/source/ARM-VFPv2/specialize.h index 5321f33..638e690 100644 --- a/softfloat/source/ARM-VFPv2/specialize.h +++ b/softfloat/source/ARM-VFPv2/specialize.h @@ -37,10 +37,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef specialize_h #define specialize_h 1 -#include -#include #include "primitiveTypes.h" #include "softfloat.h" +#include +#include /*---------------------------------------------------------------------------- | Default value for 'softfloat_detectTininess'. @@ -53,21 +53,21 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *----------------------------------------------------------------------------*/ #define ui32_fromPosOverflow 0xFFFFFFFF #define ui32_fromNegOverflow 0 -#define ui32_fromNaN 0 -#define i32_fromPosOverflow 0x7FFFFFFF -#define i32_fromNegOverflow (-0x7FFFFFFF - 1) -#define i32_fromNaN 0 +#define ui32_fromNaN 0 +#define i32_fromPosOverflow 0x7FFFFFFF +#define i32_fromNegOverflow (-0x7FFFFFFF - 1) +#define i32_fromNaN 0 /*---------------------------------------------------------------------------- | The values to return on conversions to 64-bit integer formats that raise an | invalid exception. *----------------------------------------------------------------------------*/ -#define ui64_fromPosOverflow UINT64_C( 0xFFFFFFFFFFFFFFFF ) +#define ui64_fromPosOverflow UINT64_C(0xFFFFFFFFFFFFFFFF) #define ui64_fromNegOverflow 0 -#define ui64_fromNaN 0 -#define i64_fromPosOverflow INT64_C( 0x7FFFFFFFFFFFFFFF ) -#define i64_fromNegOverflow (-INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1) -#define i64_fromNaN 0 +#define ui64_fromNaN 0 +#define i64_fromPosOverflow INT64_C(0x7FFFFFFFFFFFFFFF) +#define i64_fromNegOverflow (-INT64_C(0x7FFFFFFFFFFFFFFF) - 1) +#define i64_fromNaN 0 /*---------------------------------------------------------------------------- | "Common NaN" structure, used to transfer NaN representations from one format @@ -92,7 +92,7 @@ struct commonNaN { | 16-bit floating-point signaling NaN. | Note: This macro evaluates its argument more than once. *----------------------------------------------------------------------------*/ -#define softfloat_isSigNaNF16UI( uiA ) ((((uiA) & 0x7E00) == 0x7C00) && ((uiA) & 0x01FF)) +#define softfloat_isSigNaNF16UI(uiA) ((((uiA)&0x7E00) == 0x7C00) && ((uiA)&0x01FF)) /*---------------------------------------------------------------------------- | Assuming 'uiA' has the bit pattern of a 16-bit floating-point NaN, converts @@ -100,13 +100,13 @@ struct commonNaN { | location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid | exception is raised. *----------------------------------------------------------------------------*/ -void softfloat_f16UIToCommonNaN( uint_fast16_t uiA, struct commonNaN *zPtr ); +void softfloat_f16UIToCommonNaN(uint_fast16_t uiA, struct commonNaN* zPtr); /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by 'aPtr' into a 16-bit floating-point | NaN, and returns the bit pattern of this value as an unsigned integer. *----------------------------------------------------------------------------*/ -uint_fast16_t softfloat_commonNaNToF16UI( const struct commonNaN *aPtr ); +uint_fast16_t softfloat_commonNaNToF16UI(const struct commonNaN* aPtr); /*---------------------------------------------------------------------------- | Interpreting 'uiA' and 'uiB' as the bit patterns of two 16-bit floating- @@ -114,8 +114,7 @@ uint_fast16_t softfloat_commonNaNToF16UI( const struct commonNaN *aPtr ); | the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a | signaling NaN, the invalid exception is raised. *----------------------------------------------------------------------------*/ -uint_fast16_t - softfloat_propagateNaNF16UI( uint_fast16_t uiA, uint_fast16_t uiB ); +uint_fast16_t softfloat_propagateNaNF16UI(uint_fast16_t uiA, uint_fast16_t uiB); /*---------------------------------------------------------------------------- | The bit pattern for a default generated 32-bit floating-point NaN. @@ -127,7 +126,7 @@ uint_fast16_t | 32-bit floating-point signaling NaN. | Note: This macro evaluates its argument more than once. *----------------------------------------------------------------------------*/ -#define softfloat_isSigNaNF32UI( uiA ) ((((uiA) & 0x7FC00000) == 0x7F800000) && ((uiA) & 0x003FFFFF)) +#define softfloat_isSigNaNF32UI(uiA) ((((uiA)&0x7FC00000) == 0x7F800000) && ((uiA)&0x003FFFFF)) /*---------------------------------------------------------------------------- | Assuming 'uiA' has the bit pattern of a 32-bit floating-point NaN, converts @@ -135,13 +134,13 @@ uint_fast16_t | location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid | exception is raised. *----------------------------------------------------------------------------*/ -void softfloat_f32UIToCommonNaN( uint_fast32_t uiA, struct commonNaN *zPtr ); +void softfloat_f32UIToCommonNaN(uint_fast32_t uiA, struct commonNaN* zPtr); /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by 'aPtr' into a 32-bit floating-point | NaN, and returns the bit pattern of this value as an unsigned integer. *----------------------------------------------------------------------------*/ -uint_fast32_t softfloat_commonNaNToF32UI( const struct commonNaN *aPtr ); +uint_fast32_t softfloat_commonNaNToF32UI(const struct commonNaN* aPtr); /*---------------------------------------------------------------------------- | Interpreting 'uiA' and 'uiB' as the bit patterns of two 32-bit floating- @@ -149,20 +148,20 @@ uint_fast32_t softfloat_commonNaNToF32UI( const struct commonNaN *aPtr ); | the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a | signaling NaN, the invalid exception is raised. *----------------------------------------------------------------------------*/ -uint_fast32_t - softfloat_propagateNaNF32UI( uint_fast32_t uiA, uint_fast32_t uiB ); +uint_fast32_t softfloat_propagateNaNF32UI(uint_fast32_t uiA, uint_fast32_t uiB); /*---------------------------------------------------------------------------- | The bit pattern for a default generated 64-bit floating-point NaN. *----------------------------------------------------------------------------*/ -#define defaultNaNF64UI UINT64_C( 0x7FF8000000000000 ) +#define defaultNaNF64UI UINT64_C(0x7FF8000000000000) /*---------------------------------------------------------------------------- | Returns true when 64-bit unsigned integer 'uiA' has the bit pattern of a | 64-bit floating-point signaling NaN. | Note: This macro evaluates its argument more than once. *----------------------------------------------------------------------------*/ -#define softfloat_isSigNaNF64UI( uiA ) ((((uiA) & UINT64_C( 0x7FF8000000000000 )) == UINT64_C( 0x7FF0000000000000 )) && ((uiA) & UINT64_C( 0x0007FFFFFFFFFFFF ))) +#define softfloat_isSigNaNF64UI(uiA) \ + ((((uiA)&UINT64_C(0x7FF8000000000000)) == UINT64_C(0x7FF0000000000000)) && ((uiA)&UINT64_C(0x0007FFFFFFFFFFFF))) /*---------------------------------------------------------------------------- | Assuming 'uiA' has the bit pattern of a 64-bit floating-point NaN, converts @@ -170,13 +169,13 @@ uint_fast32_t | location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid | exception is raised. *----------------------------------------------------------------------------*/ -void softfloat_f64UIToCommonNaN( uint_fast64_t uiA, struct commonNaN *zPtr ); +void softfloat_f64UIToCommonNaN(uint_fast64_t uiA, struct commonNaN* zPtr); /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by 'aPtr' into a 64-bit floating-point | NaN, and returns the bit pattern of this value as an unsigned integer. *----------------------------------------------------------------------------*/ -uint_fast64_t softfloat_commonNaNToF64UI( const struct commonNaN *aPtr ); +uint_fast64_t softfloat_commonNaNToF64UI(const struct commonNaN* aPtr); /*---------------------------------------------------------------------------- | Interpreting 'uiA' and 'uiB' as the bit patterns of two 64-bit floating- @@ -184,14 +183,13 @@ uint_fast64_t softfloat_commonNaNToF64UI( const struct commonNaN *aPtr ); | the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a | signaling NaN, the invalid exception is raised. *----------------------------------------------------------------------------*/ -uint_fast64_t - softfloat_propagateNaNF64UI( uint_fast64_t uiA, uint_fast64_t uiB ); +uint_fast64_t softfloat_propagateNaNF64UI(uint_fast64_t uiA, uint_fast64_t uiB); /*---------------------------------------------------------------------------- | The bit pattern for a default generated 80-bit extended floating-point NaN. *----------------------------------------------------------------------------*/ #define defaultNaNExtF80UI64 0x7FFF -#define defaultNaNExtF80UI0 UINT64_C( 0xC000000000000000 ) +#define defaultNaNExtF80UI0 UINT64_C(0xC000000000000000) /*---------------------------------------------------------------------------- | Returns true when the 80-bit unsigned integer formed from concatenating @@ -199,7 +197,8 @@ uint_fast64_t | floating-point signaling NaN. | Note: This macro evaluates its arguments more than once. *----------------------------------------------------------------------------*/ -#define softfloat_isSigNaNExtF80UI( uiA64, uiA0 ) ((((uiA64) & 0x7FFF) == 0x7FFF) && ! ((uiA0) & UINT64_C( 0x4000000000000000 )) && ((uiA0) & UINT64_C( 0x3FFFFFFFFFFFFFFF ))) +#define softfloat_isSigNaNExtF80UI(uiA64, uiA0) \ + ((((uiA64)&0x7FFF) == 0x7FFF) && !((uiA0)&UINT64_C(0x4000000000000000)) && ((uiA0)&UINT64_C(0x3FFFFFFFFFFFFFFF))) #ifdef SOFTFLOAT_FAST_INT64 @@ -215,16 +214,14 @@ uint_fast64_t | location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid | exception is raised. *----------------------------------------------------------------------------*/ -void - softfloat_extF80UIToCommonNaN( - uint_fast16_t uiA64, uint_fast64_t uiA0, struct commonNaN *zPtr ); +void softfloat_extF80UIToCommonNaN(uint_fast16_t uiA64, uint_fast64_t uiA0, struct commonNaN* zPtr); /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by 'aPtr' into an 80-bit extended | floating-point NaN, and returns the bit pattern of this value as an unsigned | integer. *----------------------------------------------------------------------------*/ -struct uint128 softfloat_commonNaNToExtF80UI( const struct commonNaN *aPtr ); +struct uint128 softfloat_commonNaNToExtF80UI(const struct commonNaN* aPtr); /*---------------------------------------------------------------------------- | Interpreting the unsigned integer formed from concatenating 'uiA64' and @@ -235,19 +232,13 @@ struct uint128 softfloat_commonNaNToExtF80UI( const struct commonNaN *aPtr ); | result. If either original floating-point value is a signaling NaN, the | invalid exception is raised. *----------------------------------------------------------------------------*/ -struct uint128 - softfloat_propagateNaNExtF80UI( - uint_fast16_t uiA64, - uint_fast64_t uiA0, - uint_fast16_t uiB64, - uint_fast64_t uiB0 - ); +struct uint128 softfloat_propagateNaNExtF80UI(uint_fast16_t uiA64, uint_fast64_t uiA0, uint_fast16_t uiB64, uint_fast64_t uiB0); /*---------------------------------------------------------------------------- | The bit pattern for a default generated 128-bit floating-point NaN. *----------------------------------------------------------------------------*/ -#define defaultNaNF128UI64 UINT64_C( 0x7FFF800000000000 ) -#define defaultNaNF128UI0 UINT64_C( 0 ) +#define defaultNaNF128UI64 UINT64_C(0x7FFF800000000000) +#define defaultNaNF128UI0 UINT64_C(0) /*---------------------------------------------------------------------------- | Returns true when the 128-bit unsigned integer formed from concatenating @@ -255,7 +246,8 @@ struct uint128 | point signaling NaN. | Note: This macro evaluates its arguments more than once. *----------------------------------------------------------------------------*/ -#define softfloat_isSigNaNF128UI( uiA64, uiA0 ) ((((uiA64) & UINT64_C( 0x7FFF800000000000 )) == UINT64_C( 0x7FFF000000000000 )) && ((uiA0) || ((uiA64) & UINT64_C( 0x00007FFFFFFFFFFF )))) +#define softfloat_isSigNaNF128UI(uiA64, uiA0) \ + ((((uiA64)&UINT64_C(0x7FFF800000000000)) == UINT64_C(0x7FFF000000000000)) && ((uiA0) || ((uiA64)&UINT64_C(0x00007FFFFFFFFFFF)))) /*---------------------------------------------------------------------------- | Assuming the unsigned integer formed from concatenating 'uiA64' and 'uiA0' @@ -264,15 +256,13 @@ struct uint128 | pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid exception | is raised. *----------------------------------------------------------------------------*/ -void - softfloat_f128UIToCommonNaN( - uint_fast64_t uiA64, uint_fast64_t uiA0, struct commonNaN *zPtr ); +void softfloat_f128UIToCommonNaN(uint_fast64_t uiA64, uint_fast64_t uiA0, struct commonNaN* zPtr); /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by 'aPtr' into a 128-bit floating-point | NaN, and returns the bit pattern of this value as an unsigned integer. *----------------------------------------------------------------------------*/ -struct uint128 softfloat_commonNaNToF128UI( const struct commonNaN * ); +struct uint128 softfloat_commonNaNToF128UI(const struct commonNaN*); /*---------------------------------------------------------------------------- | Interpreting the unsigned integer formed from concatenating 'uiA64' and @@ -283,13 +273,7 @@ struct uint128 softfloat_commonNaNToF128UI( const struct commonNaN * ); | If either original floating-point value is a signaling NaN, the invalid | exception is raised. *----------------------------------------------------------------------------*/ -struct uint128 - softfloat_propagateNaNF128UI( - uint_fast64_t uiA64, - uint_fast64_t uiA0, - uint_fast64_t uiB64, - uint_fast64_t uiB0 - ); +struct uint128 softfloat_propagateNaNF128UI(uint_fast64_t uiA64, uint_fast64_t uiA0, uint_fast64_t uiB64, uint_fast64_t uiB0); #else @@ -304,18 +288,14 @@ struct uint128 | common NaN at the location pointed to by 'zPtr'. If the NaN is a signaling | NaN, the invalid exception is raised. *----------------------------------------------------------------------------*/ -void - softfloat_extF80MToCommonNaN( - const struct extFloat80M *aSPtr, struct commonNaN *zPtr ); +void softfloat_extF80MToCommonNaN(const struct extFloat80M* aSPtr, struct commonNaN* zPtr); /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by 'aPtr' into an 80-bit extended | floating-point NaN, and stores this NaN at the location pointed to by | 'zSPtr'. *----------------------------------------------------------------------------*/ -void - softfloat_commonNaNToExtF80M( - const struct commonNaN *aPtr, struct extFloat80M *zSPtr ); +void softfloat_commonNaNToExtF80M(const struct commonNaN* aPtr, struct extFloat80M* zSPtr); /*---------------------------------------------------------------------------- | Assuming at least one of the two 80-bit extended floating-point values @@ -323,12 +303,7 @@ void | at the location pointed to by 'zSPtr'. If either original floating-point | value is a signaling NaN, the invalid exception is raised. *----------------------------------------------------------------------------*/ -void - softfloat_propagateNaNExtF80M( - const struct extFloat80M *aSPtr, - const struct extFloat80M *bSPtr, - struct extFloat80M *zSPtr - ); +void softfloat_propagateNaNExtF80M(const struct extFloat80M* aSPtr, const struct extFloat80M* bSPtr, struct extFloat80M* zSPtr); /*---------------------------------------------------------------------------- | The bit pattern for a default generated 128-bit floating-point NaN. @@ -336,7 +311,7 @@ void #define defaultNaNF128UI96 0x7FFF8000 #define defaultNaNF128UI64 0 #define defaultNaNF128UI32 0 -#define defaultNaNF128UI0 0 +#define defaultNaNF128UI0 0 /*---------------------------------------------------------------------------- | Assuming the 128-bit floating-point value pointed to by 'aWPtr' is a NaN, @@ -346,8 +321,7 @@ void | four 32-bit elements that concatenate in the platform's normal endian order | to form a 128-bit floating-point value. *----------------------------------------------------------------------------*/ -void - softfloat_f128MToCommonNaN( const uint32_t *aWPtr, struct commonNaN *zPtr ); +void softfloat_f128MToCommonNaN(const uint32_t* aWPtr, struct commonNaN* zPtr); /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by 'aPtr' into a 128-bit floating-point @@ -355,8 +329,7 @@ void | 'zWPtr' points to an array of four 32-bit elements that concatenate in the | platform's normal endian order to form a 128-bit floating-point value. *----------------------------------------------------------------------------*/ -void - softfloat_commonNaNToF128M( const struct commonNaN *aPtr, uint32_t *zWPtr ); +void softfloat_commonNaNToF128M(const struct commonNaN* aPtr, uint32_t* zWPtr); /*---------------------------------------------------------------------------- | Assuming at least one of the two 128-bit floating-point values pointed to by @@ -366,11 +339,8 @@ void | and 'zWPtr' points to an array of four 32-bit elements that concatenate in | the platform's normal endian order to form a 128-bit floating-point value. *----------------------------------------------------------------------------*/ -void - softfloat_propagateNaNF128M( - const uint32_t *aWPtr, const uint32_t *bWPtr, uint32_t *zWPtr ); +void softfloat_propagateNaNF128M(const uint32_t* aWPtr, const uint32_t* bWPtr, uint32_t* zWPtr); #endif #endif - diff --git a/softfloat/source/RISCV/specialize.h b/softfloat/source/RISCV/specialize.h index 1cb9854..f0cb14c 100644 --- a/softfloat/source/RISCV/specialize.h +++ b/softfloat/source/RISCV/specialize.h @@ -37,10 +37,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef specialize_h #define specialize_h 1 -#include -#include #include "primitiveTypes.h" #include "softfloat.h" +#include +#include /*---------------------------------------------------------------------------- | Default value for 'softfloat_detectTininess'. @@ -53,21 +53,21 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *----------------------------------------------------------------------------*/ #define ui32_fromPosOverflow UINT32_C(0xFFFFFFFF) #define ui32_fromNegOverflow UINT32_C(0x0) -#define ui32_fromNaN UINT32_C(0xFFFFFFFF) -#define i32_fromPosOverflow INT64_C(0x7FFFFFFF) -#define i32_fromNegOverflow (-INT64_C(0x7FFFFFFF)-1) -#define i32_fromNaN INT64_C(0x7FFFFFFF) +#define ui32_fromNaN UINT32_C(0xFFFFFFFF) +#define i32_fromPosOverflow INT64_C(0x7FFFFFFF) +#define i32_fromNegOverflow (-INT64_C(0x7FFFFFFF) - 1) +#define i32_fromNaN INT64_C(0x7FFFFFFF) /*---------------------------------------------------------------------------- | The values to return on conversions to 64-bit integer formats that raise an | invalid exception. *----------------------------------------------------------------------------*/ -#define ui64_fromPosOverflow UINT64_C( 0xFFFFFFFFFFFFFFFF ) -#define ui64_fromNegOverflow UINT64_C( 0x0 ) -#define ui64_fromNaN UINT64_C( 0xFFFFFFFFFFFFFFFF) -#define i64_fromPosOverflow INT64_C( 0x7FFFFFFFFFFFFFFF) -#define i64_fromNegOverflow (-INT64_C( 0x7FFFFFFFFFFFFFFF)-1) -#define i64_fromNaN INT64_C( 0x7FFFFFFFFFFFFFFF) +#define ui64_fromPosOverflow UINT64_C(0xFFFFFFFFFFFFFFFF) +#define ui64_fromNegOverflow UINT64_C(0x0) +#define ui64_fromNaN UINT64_C(0xFFFFFFFFFFFFFFFF) +#define i64_fromPosOverflow INT64_C(0x7FFFFFFFFFFFFFFF) +#define i64_fromNegOverflow (-INT64_C(0x7FFFFFFFFFFFFFFF) - 1) +#define i64_fromNaN INT64_C(0x7FFFFFFFFFFFFFFF) /*---------------------------------------------------------------------------- | "Common NaN" structure, used to transfer NaN representations from one format @@ -92,7 +92,7 @@ struct commonNaN { | 16-bit floating-point signaling NaN. | Note: This macro evaluates its argument more than once. *----------------------------------------------------------------------------*/ -#define softfloat_isSigNaNF16UI( uiA ) ((((uiA) & 0x7E00) == 0x7C00) && ((uiA) & 0x01FF)) +#define softfloat_isSigNaNF16UI(uiA) ((((uiA)&0x7E00) == 0x7C00) && ((uiA)&0x01FF)) /*---------------------------------------------------------------------------- | Assuming 'uiA' has the bit pattern of a 16-bit floating-point NaN, converts @@ -100,13 +100,13 @@ struct commonNaN { | location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid | exception is raised. *----------------------------------------------------------------------------*/ -void softfloat_f16UIToCommonNaN( uint_fast16_t uiA, struct commonNaN *zPtr ); +void softfloat_f16UIToCommonNaN(uint_fast16_t uiA, struct commonNaN* zPtr); /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by 'aPtr' into a 16-bit floating-point | NaN, and returns the bit pattern of this value as an unsigned integer. *----------------------------------------------------------------------------*/ -uint_fast16_t softfloat_commonNaNToF16UI( const struct commonNaN *aPtr ); +uint_fast16_t softfloat_commonNaNToF16UI(const struct commonNaN* aPtr); /*---------------------------------------------------------------------------- | Interpreting 'uiA' and 'uiB' as the bit patterns of two 16-bit floating- @@ -114,8 +114,7 @@ uint_fast16_t softfloat_commonNaNToF16UI( const struct commonNaN *aPtr ); | the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a | signaling NaN, the invalid exception is raised. *----------------------------------------------------------------------------*/ -uint_fast16_t - softfloat_propagateNaNF16UI( uint_fast16_t uiA, uint_fast16_t uiB ); +uint_fast16_t softfloat_propagateNaNF16UI(uint_fast16_t uiA, uint_fast16_t uiB); /*---------------------------------------------------------------------------- | The bit pattern for a default generated 32-bit floating-point NaN. @@ -127,7 +126,7 @@ uint_fast16_t | 32-bit floating-point signaling NaN. | Note: This macro evaluates its argument more than once. *----------------------------------------------------------------------------*/ -#define softfloat_isSigNaNF32UI( uiA ) ((((uiA) & 0x7FC00000) == 0x7F800000) && ((uiA) & 0x003FFFFF)) +#define softfloat_isSigNaNF32UI(uiA) ((((uiA)&0x7FC00000) == 0x7F800000) && ((uiA)&0x003FFFFF)) /*---------------------------------------------------------------------------- | Assuming 'uiA' has the bit pattern of a 32-bit floating-point NaN, converts @@ -135,13 +134,13 @@ uint_fast16_t | location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid | exception is raised. *----------------------------------------------------------------------------*/ -void softfloat_f32UIToCommonNaN( uint_fast32_t uiA, struct commonNaN *zPtr ); +void softfloat_f32UIToCommonNaN(uint_fast32_t uiA, struct commonNaN* zPtr); /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by 'aPtr' into a 32-bit floating-point | NaN, and returns the bit pattern of this value as an unsigned integer. *----------------------------------------------------------------------------*/ -uint_fast32_t softfloat_commonNaNToF32UI( const struct commonNaN *aPtr ); +uint_fast32_t softfloat_commonNaNToF32UI(const struct commonNaN* aPtr); /*---------------------------------------------------------------------------- | Interpreting 'uiA' and 'uiB' as the bit patterns of two 32-bit floating- @@ -149,20 +148,20 @@ uint_fast32_t softfloat_commonNaNToF32UI( const struct commonNaN *aPtr ); | the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a | signaling NaN, the invalid exception is raised. *----------------------------------------------------------------------------*/ -uint_fast32_t - softfloat_propagateNaNF32UI( uint_fast32_t uiA, uint_fast32_t uiB ); +uint_fast32_t softfloat_propagateNaNF32UI(uint_fast32_t uiA, uint_fast32_t uiB); /*---------------------------------------------------------------------------- | The bit pattern for a default generated 64-bit floating-point NaN. *----------------------------------------------------------------------------*/ -#define defaultNaNF64UI UINT64_C( 0x7FF8000000000000 ) +#define defaultNaNF64UI UINT64_C(0x7FF8000000000000) /*---------------------------------------------------------------------------- | Returns true when 64-bit unsigned integer 'uiA' has the bit pattern of a | 64-bit floating-point signaling NaN. | Note: This macro evaluates its argument more than once. *----------------------------------------------------------------------------*/ -#define softfloat_isSigNaNF64UI( uiA ) ((((uiA) & UINT64_C( 0x7FF8000000000000 )) == UINT64_C( 0x7FF0000000000000 )) && ((uiA) & UINT64_C( 0x0007FFFFFFFFFFFF ))) +#define softfloat_isSigNaNF64UI(uiA) \ + ((((uiA)&UINT64_C(0x7FF8000000000000)) == UINT64_C(0x7FF0000000000000)) && ((uiA)&UINT64_C(0x0007FFFFFFFFFFFF))) /*---------------------------------------------------------------------------- | Assuming 'uiA' has the bit pattern of a 64-bit floating-point NaN, converts @@ -170,13 +169,13 @@ uint_fast32_t | location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid | exception is raised. *----------------------------------------------------------------------------*/ -void softfloat_f64UIToCommonNaN( uint_fast64_t uiA, struct commonNaN *zPtr ); +void softfloat_f64UIToCommonNaN(uint_fast64_t uiA, struct commonNaN* zPtr); /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by 'aPtr' into a 64-bit floating-point | NaN, and returns the bit pattern of this value as an unsigned integer. *----------------------------------------------------------------------------*/ -uint_fast64_t softfloat_commonNaNToF64UI( const struct commonNaN *aPtr ); +uint_fast64_t softfloat_commonNaNToF64UI(const struct commonNaN* aPtr); /*---------------------------------------------------------------------------- | Interpreting 'uiA' and 'uiB' as the bit patterns of two 64-bit floating- @@ -184,14 +183,13 @@ uint_fast64_t softfloat_commonNaNToF64UI( const struct commonNaN *aPtr ); | the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a | signaling NaN, the invalid exception is raised. *----------------------------------------------------------------------------*/ -uint_fast64_t - softfloat_propagateNaNF64UI( uint_fast64_t uiA, uint_fast64_t uiB ); +uint_fast64_t softfloat_propagateNaNF64UI(uint_fast64_t uiA, uint_fast64_t uiB); /*---------------------------------------------------------------------------- | The bit pattern for a default generated 80-bit extended floating-point NaN. *----------------------------------------------------------------------------*/ #define defaultNaNExtF80UI64 0xFFFF -#define defaultNaNExtF80UI0 UINT64_C( 0xC000000000000000 ) +#define defaultNaNExtF80UI0 UINT64_C(0xC000000000000000) /*---------------------------------------------------------------------------- | Returns true when the 80-bit unsigned integer formed from concatenating @@ -199,7 +197,8 @@ uint_fast64_t | floating-point signaling NaN. | Note: This macro evaluates its arguments more than once. *----------------------------------------------------------------------------*/ -#define softfloat_isSigNaNExtF80UI( uiA64, uiA0 ) ((((uiA64) & 0x7FFF) == 0x7FFF) && ! ((uiA0) & UINT64_C( 0x4000000000000000 )) && ((uiA0) & UINT64_C( 0x3FFFFFFFFFFFFFFF ))) +#define softfloat_isSigNaNExtF80UI(uiA64, uiA0) \ + ((((uiA64)&0x7FFF) == 0x7FFF) && !((uiA0)&UINT64_C(0x4000000000000000)) && ((uiA0)&UINT64_C(0x3FFFFFFFFFFFFFFF))) #ifdef SOFTFLOAT_FAST_INT64 @@ -215,16 +214,14 @@ uint_fast64_t | location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid | exception is raised. *----------------------------------------------------------------------------*/ -void - softfloat_extF80UIToCommonNaN( - uint_fast16_t uiA64, uint_fast64_t uiA0, struct commonNaN *zPtr ); +void softfloat_extF80UIToCommonNaN(uint_fast16_t uiA64, uint_fast64_t uiA0, struct commonNaN* zPtr); /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by 'aPtr' into an 80-bit extended | floating-point NaN, and returns the bit pattern of this value as an unsigned | integer. *----------------------------------------------------------------------------*/ -struct uint128 softfloat_commonNaNToExtF80UI( const struct commonNaN *aPtr ); +struct uint128 softfloat_commonNaNToExtF80UI(const struct commonNaN* aPtr); /*---------------------------------------------------------------------------- | Interpreting the unsigned integer formed from concatenating 'uiA64' and @@ -235,19 +232,13 @@ struct uint128 softfloat_commonNaNToExtF80UI( const struct commonNaN *aPtr ); | result. If either original floating-point value is a signaling NaN, the | invalid exception is raised. *----------------------------------------------------------------------------*/ -struct uint128 - softfloat_propagateNaNExtF80UI( - uint_fast16_t uiA64, - uint_fast64_t uiA0, - uint_fast16_t uiB64, - uint_fast64_t uiB0 - ); +struct uint128 softfloat_propagateNaNExtF80UI(uint_fast16_t uiA64, uint_fast64_t uiA0, uint_fast16_t uiB64, uint_fast64_t uiB0); /*---------------------------------------------------------------------------- | The bit pattern for a default generated 128-bit floating-point NaN. *----------------------------------------------------------------------------*/ -#define defaultNaNF128UI64 UINT64_C( 0xFFFF800000000000 ) -#define defaultNaNF128UI0 UINT64_C( 0 ) +#define defaultNaNF128UI64 UINT64_C(0xFFFF800000000000) +#define defaultNaNF128UI0 UINT64_C(0) /*---------------------------------------------------------------------------- | Returns true when the 128-bit unsigned integer formed from concatenating @@ -255,7 +246,8 @@ struct uint128 | point signaling NaN. | Note: This macro evaluates its arguments more than once. *----------------------------------------------------------------------------*/ -#define softfloat_isSigNaNF128UI( uiA64, uiA0 ) ((((uiA64) & UINT64_C( 0x7FFF800000000000 )) == UINT64_C( 0x7FFF000000000000 )) && ((uiA0) || ((uiA64) & UINT64_C( 0x00007FFFFFFFFFFF )))) +#define softfloat_isSigNaNF128UI(uiA64, uiA0) \ + ((((uiA64)&UINT64_C(0x7FFF800000000000)) == UINT64_C(0x7FFF000000000000)) && ((uiA0) || ((uiA64)&UINT64_C(0x00007FFFFFFFFFFF)))) /*---------------------------------------------------------------------------- | Assuming the unsigned integer formed from concatenating 'uiA64' and 'uiA0' @@ -264,15 +256,13 @@ struct uint128 | pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid exception | is raised. *----------------------------------------------------------------------------*/ -void - softfloat_f128UIToCommonNaN( - uint_fast64_t uiA64, uint_fast64_t uiA0, struct commonNaN *zPtr ); +void softfloat_f128UIToCommonNaN(uint_fast64_t uiA64, uint_fast64_t uiA0, struct commonNaN* zPtr); /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by 'aPtr' into a 128-bit floating-point | NaN, and returns the bit pattern of this value as an unsigned integer. *----------------------------------------------------------------------------*/ -struct uint128 softfloat_commonNaNToF128UI( const struct commonNaN * ); +struct uint128 softfloat_commonNaNToF128UI(const struct commonNaN*); /*---------------------------------------------------------------------------- | Interpreting the unsigned integer formed from concatenating 'uiA64' and @@ -283,13 +273,7 @@ struct uint128 softfloat_commonNaNToF128UI( const struct commonNaN * ); | If either original floating-point value is a signaling NaN, the invalid | exception is raised. *----------------------------------------------------------------------------*/ -struct uint128 - softfloat_propagateNaNF128UI( - uint_fast64_t uiA64, - uint_fast64_t uiA0, - uint_fast64_t uiB64, - uint_fast64_t uiB0 - ); +struct uint128 softfloat_propagateNaNF128UI(uint_fast64_t uiA64, uint_fast64_t uiA0, uint_fast64_t uiB64, uint_fast64_t uiB0); #else @@ -304,18 +288,14 @@ struct uint128 | common NaN at the location pointed to by 'zPtr'. If the NaN is a signaling | NaN, the invalid exception is raised. *----------------------------------------------------------------------------*/ -void - softfloat_extF80MToCommonNaN( - const struct extFloat80M *aSPtr, struct commonNaN *zPtr ); +void softfloat_extF80MToCommonNaN(const struct extFloat80M* aSPtr, struct commonNaN* zPtr); /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by 'aPtr' into an 80-bit extended | floating-point NaN, and stores this NaN at the location pointed to by | 'zSPtr'. *----------------------------------------------------------------------------*/ -void - softfloat_commonNaNToExtF80M( - const struct commonNaN *aPtr, struct extFloat80M *zSPtr ); +void softfloat_commonNaNToExtF80M(const struct commonNaN* aPtr, struct extFloat80M* zSPtr); /*---------------------------------------------------------------------------- | Assuming at least one of the two 80-bit extended floating-point values @@ -323,12 +303,7 @@ void | at the location pointed to by 'zSPtr'. If either original floating-point | value is a signaling NaN, the invalid exception is raised. *----------------------------------------------------------------------------*/ -void - softfloat_propagateNaNExtF80M( - const struct extFloat80M *aSPtr, - const struct extFloat80M *bSPtr, - struct extFloat80M *zSPtr - ); +void softfloat_propagateNaNExtF80M(const struct extFloat80M* aSPtr, const struct extFloat80M* bSPtr, struct extFloat80M* zSPtr); /*---------------------------------------------------------------------------- | The bit pattern for a default generated 128-bit floating-point NaN. @@ -336,7 +311,7 @@ void #define defaultNaNF128UI96 0xFFFF8000 #define defaultNaNF128UI64 0 #define defaultNaNF128UI32 0 -#define defaultNaNF128UI0 0 +#define defaultNaNF128UI0 0 /*---------------------------------------------------------------------------- | Assuming the 128-bit floating-point value pointed to by 'aWPtr' is a NaN, @@ -346,8 +321,7 @@ void | four 32-bit elements that concatenate in the platform's normal endian order | to form a 128-bit floating-point value. *----------------------------------------------------------------------------*/ -void - softfloat_f128MToCommonNaN( const uint32_t *aWPtr, struct commonNaN *zPtr ); +void softfloat_f128MToCommonNaN(const uint32_t* aWPtr, struct commonNaN* zPtr); /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by 'aPtr' into a 128-bit floating-point @@ -355,8 +329,7 @@ void | 'zWPtr' points to an array of four 32-bit elements that concatenate in the | platform's normal endian order to form a 128-bit floating-point value. *----------------------------------------------------------------------------*/ -void - softfloat_commonNaNToF128M( const struct commonNaN *aPtr, uint32_t *zWPtr ); +void softfloat_commonNaNToF128M(const struct commonNaN* aPtr, uint32_t* zWPtr); /*---------------------------------------------------------------------------- | Assuming at least one of the two 128-bit floating-point values pointed to by @@ -366,11 +339,8 @@ void | and 'zWPtr' points to an array of four 32-bit elements that concatenate in | the platform's normal endian order to form a 128-bit floating-point value. *----------------------------------------------------------------------------*/ -void - softfloat_propagateNaNF128M( - const uint32_t *aWPtr, const uint32_t *bWPtr, uint32_t *zWPtr ); +void softfloat_propagateNaNF128M(const uint32_t* aWPtr, const uint32_t* bWPtr, uint32_t* zWPtr); #endif #endif - diff --git a/softfloat/source/include/internals.h b/softfloat/source/include/internals.h index 020b340..bd976d1 100644 --- a/softfloat/source/include/internals.h +++ b/softfloat/source/include/internals.h @@ -37,242 +37,205 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef internals_h #define internals_h 1 -#include -#include #include "primitives.h" #include "softfloat_types.h" +#include +#include -union ui16_f16 { uint16_t ui; float16_t f; }; -union ui32_f32 { uint32_t ui; float32_t f; }; -union ui64_f64 { uint64_t ui; float64_t f; }; - -#ifdef SOFTFLOAT_FAST_INT64 -union extF80M_extF80 { struct extFloat80M fM; extFloat80_t f; }; -union ui128_f128 { struct uint128 ui; float128_t f; }; -#endif - -enum { - softfloat_mulAdd_subC = 1, - softfloat_mulAdd_subProd = 2 +union ui16_f16 { + uint16_t ui; + float16_t f; +}; +union ui32_f32 { + uint32_t ui; + float32_t f; +}; +union ui64_f64 { + uint64_t ui; + float64_t f; }; -/*---------------------------------------------------------------------------- -*----------------------------------------------------------------------------*/ -uint_fast32_t softfloat_roundToUI32( bool, uint_fast64_t, uint_fast8_t, bool ); - #ifdef SOFTFLOAT_FAST_INT64 -uint_fast64_t - softfloat_roundToUI64( - bool, uint_fast64_t, uint_fast64_t, uint_fast8_t, bool ); -#else -uint_fast64_t softfloat_roundMToUI64( bool, uint32_t *, uint_fast8_t, bool ); +union extF80M_extF80 { + struct extFloat80M fM; + extFloat80_t f; +}; +union ui128_f128 { + struct uint128 ui; + float128_t f; +}; #endif -int_fast32_t softfloat_roundToI32( bool, uint_fast64_t, uint_fast8_t, bool ); +enum { softfloat_mulAdd_subC = 1, softfloat_mulAdd_subProd = 2 }; + +/*---------------------------------------------------------------------------- + *----------------------------------------------------------------------------*/ +uint_fast32_t softfloat_roundToUI32(bool, uint_fast64_t, uint_fast8_t, bool); #ifdef SOFTFLOAT_FAST_INT64 -int_fast64_t - softfloat_roundToI64( - bool, uint_fast64_t, uint_fast64_t, uint_fast8_t, bool ); +uint_fast64_t softfloat_roundToUI64(bool, uint_fast64_t, uint_fast64_t, uint_fast8_t, bool); #else -int_fast64_t softfloat_roundMToI64( bool, uint32_t *, uint_fast8_t, bool ); +uint_fast64_t softfloat_roundMToUI64(bool, uint32_t*, uint_fast8_t, bool); +#endif + +int_fast32_t softfloat_roundToI32(bool, uint_fast64_t, uint_fast8_t, bool); + +#ifdef SOFTFLOAT_FAST_INT64 +int_fast64_t softfloat_roundToI64(bool, uint_fast64_t, uint_fast64_t, uint_fast8_t, bool); +#else +int_fast64_t softfloat_roundMToI64(bool, uint32_t*, uint_fast8_t, bool); #endif /*---------------------------------------------------------------------------- -*----------------------------------------------------------------------------*/ -#define signF16UI( a ) ((bool) ((uint16_t) (a)>>15)) -#define expF16UI( a ) ((int_fast8_t) ((a)>>10) & 0x1F) -#define fracF16UI( a ) ((a) & 0x03FF) -#define packToF16UI( sign, exp, sig ) (((uint16_t) (sign)<<15) + ((uint16_t) (exp)<<10) + (sig)) + *----------------------------------------------------------------------------*/ +#define signF16UI(a) ((bool)((uint16_t)(a) >> 15)) +#define expF16UI(a) ((int_fast8_t)((a) >> 10) & 0x1F) +#define fracF16UI(a) ((a)&0x03FF) +#define packToF16UI(sign, exp, sig) (((uint16_t)(sign) << 15) + ((uint16_t)(exp) << 10) + (sig)) -#define isNaNF16UI( a ) (((~(a) & 0x7C00) == 0) && ((a) & 0x03FF)) +#define isNaNF16UI(a) (((~(a)&0x7C00) == 0) && ((a)&0x03FF)) -struct exp8_sig16 { int_fast8_t exp; uint_fast16_t sig; }; -struct exp8_sig16 softfloat_normSubnormalF16Sig( uint_fast16_t ); +struct exp8_sig16 { + int_fast8_t exp; + uint_fast16_t sig; +}; +struct exp8_sig16 softfloat_normSubnormalF16Sig(uint_fast16_t); -float16_t softfloat_roundPackToF16( bool, int_fast16_t, uint_fast16_t ); -float16_t softfloat_normRoundPackToF16( bool, int_fast16_t, uint_fast16_t ); +float16_t softfloat_roundPackToF16(bool, int_fast16_t, uint_fast16_t); +float16_t softfloat_normRoundPackToF16(bool, int_fast16_t, uint_fast16_t); -float16_t softfloat_addMagsF16( uint_fast16_t, uint_fast16_t ); -float16_t softfloat_subMagsF16( uint_fast16_t, uint_fast16_t ); -float16_t - softfloat_mulAddF16( - uint_fast16_t, uint_fast16_t, uint_fast16_t, uint_fast8_t ); +float16_t softfloat_addMagsF16(uint_fast16_t, uint_fast16_t); +float16_t softfloat_subMagsF16(uint_fast16_t, uint_fast16_t); +float16_t softfloat_mulAddF16(uint_fast16_t, uint_fast16_t, uint_fast16_t, uint_fast8_t); /*---------------------------------------------------------------------------- -*----------------------------------------------------------------------------*/ -#define signF32UI( a ) ((bool) ((uint32_t) (a)>>31)) -#define expF32UI( a ) ((int_fast16_t) ((a)>>23) & 0xFF) -#define fracF32UI( a ) ((a) & 0x007FFFFF) -#define packToF32UI( sign, exp, sig ) (((uint32_t) (sign)<<31) + ((uint32_t) (exp)<<23) + (sig)) + *----------------------------------------------------------------------------*/ +#define signF32UI(a) ((bool)((uint32_t)(a) >> 31)) +#define expF32UI(a) ((int_fast16_t)((a) >> 23) & 0xFF) +#define fracF32UI(a) ((a)&0x007FFFFF) +#define packToF32UI(sign, exp, sig) (((uint32_t)(sign) << 31) + ((uint32_t)(exp) << 23) + (sig)) -#define isNaNF32UI( a ) (((~(a) & 0x7F800000) == 0) && ((a) & 0x007FFFFF)) +#define isNaNF32UI(a) (((~(a)&0x7F800000) == 0) && ((a)&0x007FFFFF)) -struct exp16_sig32 { int_fast16_t exp; uint_fast32_t sig; }; -struct exp16_sig32 softfloat_normSubnormalF32Sig( uint_fast32_t ); +struct exp16_sig32 { + int_fast16_t exp; + uint_fast32_t sig; +}; +struct exp16_sig32 softfloat_normSubnormalF32Sig(uint_fast32_t); -float32_t softfloat_roundPackToF32( bool, int_fast16_t, uint_fast32_t ); -float32_t softfloat_normRoundPackToF32( bool, int_fast16_t, uint_fast32_t ); +float32_t softfloat_roundPackToF32(bool, int_fast16_t, uint_fast32_t); +float32_t softfloat_normRoundPackToF32(bool, int_fast16_t, uint_fast32_t); -float32_t softfloat_addMagsF32( uint_fast32_t, uint_fast32_t ); -float32_t softfloat_subMagsF32( uint_fast32_t, uint_fast32_t ); -float32_t - softfloat_mulAddF32( - uint_fast32_t, uint_fast32_t, uint_fast32_t, uint_fast8_t ); +float32_t softfloat_addMagsF32(uint_fast32_t, uint_fast32_t); +float32_t softfloat_subMagsF32(uint_fast32_t, uint_fast32_t); +float32_t softfloat_mulAddF32(uint_fast32_t, uint_fast32_t, uint_fast32_t, uint_fast8_t); /*---------------------------------------------------------------------------- -*----------------------------------------------------------------------------*/ -#define signF64UI( a ) ((bool) ((uint64_t) (a)>>63)) -#define expF64UI( a ) ((int_fast16_t) ((a)>>52) & 0x7FF) -#define fracF64UI( a ) ((a) & UINT64_C( 0x000FFFFFFFFFFFFF )) -#define packToF64UI( sign, exp, sig ) ((uint64_t) (((uint_fast64_t) (sign)<<63) + ((uint_fast64_t) (exp)<<52) + (sig))) + *----------------------------------------------------------------------------*/ +#define signF64UI(a) ((bool)((uint64_t)(a) >> 63)) +#define expF64UI(a) ((int_fast16_t)((a) >> 52) & 0x7FF) +#define fracF64UI(a) ((a)&UINT64_C(0x000FFFFFFFFFFFFF)) +#define packToF64UI(sign, exp, sig) ((uint64_t)(((uint_fast64_t)(sign) << 63) + ((uint_fast64_t)(exp) << 52) + (sig))) -#define isNaNF64UI( a ) (((~(a) & UINT64_C( 0x7FF0000000000000 )) == 0) && ((a) & UINT64_C( 0x000FFFFFFFFFFFFF ))) +#define isNaNF64UI(a) (((~(a)&UINT64_C(0x7FF0000000000000)) == 0) && ((a)&UINT64_C(0x000FFFFFFFFFFFFF))) -struct exp16_sig64 { int_fast16_t exp; uint_fast64_t sig; }; -struct exp16_sig64 softfloat_normSubnormalF64Sig( uint_fast64_t ); +struct exp16_sig64 { + int_fast16_t exp; + uint_fast64_t sig; +}; +struct exp16_sig64 softfloat_normSubnormalF64Sig(uint_fast64_t); -float64_t softfloat_roundPackToF64( bool, int_fast16_t, uint_fast64_t ); -float64_t softfloat_normRoundPackToF64( bool, int_fast16_t, uint_fast64_t ); +float64_t softfloat_roundPackToF64(bool, int_fast16_t, uint_fast64_t); +float64_t softfloat_normRoundPackToF64(bool, int_fast16_t, uint_fast64_t); -float64_t softfloat_addMagsF64( uint_fast64_t, uint_fast64_t, bool ); -float64_t softfloat_subMagsF64( uint_fast64_t, uint_fast64_t, bool ); -float64_t - softfloat_mulAddF64( - uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast8_t ); +float64_t softfloat_addMagsF64(uint_fast64_t, uint_fast64_t, bool); +float64_t softfloat_subMagsF64(uint_fast64_t, uint_fast64_t, bool); +float64_t softfloat_mulAddF64(uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast8_t); /*---------------------------------------------------------------------------- -*----------------------------------------------------------------------------*/ -#define signExtF80UI64( a64 ) ((bool) ((uint16_t) (a64)>>15)) -#define expExtF80UI64( a64 ) ((a64) & 0x7FFF) -#define packToExtF80UI64( sign, exp ) ((uint_fast16_t) (sign)<<15 | (exp)) + *----------------------------------------------------------------------------*/ +#define signExtF80UI64(a64) ((bool)((uint16_t)(a64) >> 15)) +#define expExtF80UI64(a64) ((a64)&0x7FFF) +#define packToExtF80UI64(sign, exp) ((uint_fast16_t)(sign) << 15 | (exp)) -#define isNaNExtF80UI( a64, a0 ) ((((a64) & 0x7FFF) == 0x7FFF) && ((a0) & UINT64_C( 0x7FFFFFFFFFFFFFFF ))) +#define isNaNExtF80UI(a64, a0) ((((a64)&0x7FFF) == 0x7FFF) && ((a0)&UINT64_C(0x7FFFFFFFFFFFFFFF))) #ifdef SOFTFLOAT_FAST_INT64 /*---------------------------------------------------------------------------- -*----------------------------------------------------------------------------*/ + *----------------------------------------------------------------------------*/ -struct exp32_sig64 { int_fast32_t exp; uint64_t sig; }; -struct exp32_sig64 softfloat_normSubnormalExtF80Sig( uint_fast64_t ); +struct exp32_sig64 { + int_fast32_t exp; + uint64_t sig; +}; +struct exp32_sig64 softfloat_normSubnormalExtF80Sig(uint_fast64_t); -extFloat80_t - softfloat_roundPackToExtF80( - bool, int_fast32_t, uint_fast64_t, uint_fast64_t, uint_fast8_t ); -extFloat80_t - softfloat_normRoundPackToExtF80( - bool, int_fast32_t, uint_fast64_t, uint_fast64_t, uint_fast8_t ); +extFloat80_t softfloat_roundPackToExtF80(bool, int_fast32_t, uint_fast64_t, uint_fast64_t, uint_fast8_t); +extFloat80_t softfloat_normRoundPackToExtF80(bool, int_fast32_t, uint_fast64_t, uint_fast64_t, uint_fast8_t); -extFloat80_t - softfloat_addMagsExtF80( - uint_fast16_t, uint_fast64_t, uint_fast16_t, uint_fast64_t, bool ); -extFloat80_t - softfloat_subMagsExtF80( - uint_fast16_t, uint_fast64_t, uint_fast16_t, uint_fast64_t, bool ); +extFloat80_t softfloat_addMagsExtF80(uint_fast16_t, uint_fast64_t, uint_fast16_t, uint_fast64_t, bool); +extFloat80_t softfloat_subMagsExtF80(uint_fast16_t, uint_fast64_t, uint_fast16_t, uint_fast64_t, bool); /*---------------------------------------------------------------------------- -*----------------------------------------------------------------------------*/ -#define signF128UI64( a64 ) ((bool) ((uint64_t) (a64)>>63)) -#define expF128UI64( a64 ) ((int_fast32_t) ((a64)>>48) & 0x7FFF) -#define fracF128UI64( a64 ) ((a64) & UINT64_C( 0x0000FFFFFFFFFFFF )) -#define packToF128UI64( sign, exp, sig64 ) (((uint_fast64_t) (sign)<<63) + ((uint_fast64_t) (exp)<<48) + (sig64)) + *----------------------------------------------------------------------------*/ +#define signF128UI64(a64) ((bool)((uint64_t)(a64) >> 63)) +#define expF128UI64(a64) ((int_fast32_t)((a64) >> 48) & 0x7FFF) +#define fracF128UI64(a64) ((a64)&UINT64_C(0x0000FFFFFFFFFFFF)) +#define packToF128UI64(sign, exp, sig64) (((uint_fast64_t)(sign) << 63) + ((uint_fast64_t)(exp) << 48) + (sig64)) -#define isNaNF128UI( a64, a0 ) (((~(a64) & UINT64_C( 0x7FFF000000000000 )) == 0) && (a0 || ((a64) & UINT64_C( 0x0000FFFFFFFFFFFF )))) +#define isNaNF128UI(a64, a0) (((~(a64)&UINT64_C(0x7FFF000000000000)) == 0) && (a0 || ((a64)&UINT64_C(0x0000FFFFFFFFFFFF)))) -struct exp32_sig128 { int_fast32_t exp; struct uint128 sig; }; -struct exp32_sig128 - softfloat_normSubnormalF128Sig( uint_fast64_t, uint_fast64_t ); +struct exp32_sig128 { + int_fast32_t exp; + struct uint128 sig; +}; +struct exp32_sig128 softfloat_normSubnormalF128Sig(uint_fast64_t, uint_fast64_t); -float128_t - softfloat_roundPackToF128( - bool, int_fast32_t, uint_fast64_t, uint_fast64_t, uint_fast64_t ); -float128_t - softfloat_normRoundPackToF128( - bool, int_fast32_t, uint_fast64_t, uint_fast64_t ); +float128_t softfloat_roundPackToF128(bool, int_fast32_t, uint_fast64_t, uint_fast64_t, uint_fast64_t); +float128_t softfloat_normRoundPackToF128(bool, int_fast32_t, uint_fast64_t, uint_fast64_t); -float128_t - softfloat_addMagsF128( - uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast64_t, bool ); -float128_t - softfloat_subMagsF128( - uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast64_t, bool ); -float128_t - softfloat_mulAddF128( - uint_fast64_t, - uint_fast64_t, - uint_fast64_t, - uint_fast64_t, - uint_fast64_t, - uint_fast64_t, - uint_fast8_t - ); +float128_t softfloat_addMagsF128(uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast64_t, bool); +float128_t softfloat_subMagsF128(uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast64_t, bool); +float128_t softfloat_mulAddF128(uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast8_t); #else /*---------------------------------------------------------------------------- -*----------------------------------------------------------------------------*/ + *----------------------------------------------------------------------------*/ -bool - softfloat_tryPropagateNaNExtF80M( - const struct extFloat80M *, - const struct extFloat80M *, - struct extFloat80M * - ); -void softfloat_invalidExtF80M( struct extFloat80M * ); +bool softfloat_tryPropagateNaNExtF80M(const struct extFloat80M*, const struct extFloat80M*, struct extFloat80M*); +void softfloat_invalidExtF80M(struct extFloat80M*); -int softfloat_normExtF80SigM( uint64_t * ); +int softfloat_normExtF80SigM(uint64_t*); -void - softfloat_roundPackMToExtF80M( - bool, int32_t, uint32_t *, uint_fast8_t, struct extFloat80M * ); -void - softfloat_normRoundPackMToExtF80M( - bool, int32_t, uint32_t *, uint_fast8_t, struct extFloat80M * ); +void softfloat_roundPackMToExtF80M(bool, int32_t, uint32_t*, uint_fast8_t, struct extFloat80M*); +void softfloat_normRoundPackMToExtF80M(bool, int32_t, uint32_t*, uint_fast8_t, struct extFloat80M*); -void - softfloat_addExtF80M( - const struct extFloat80M *, - const struct extFloat80M *, - struct extFloat80M *, - bool - ); +void softfloat_addExtF80M(const struct extFloat80M*, const struct extFloat80M*, struct extFloat80M*, bool); -int - softfloat_compareNonnormExtF80M( - const struct extFloat80M *, const struct extFloat80M * ); +int softfloat_compareNonnormExtF80M(const struct extFloat80M*, const struct extFloat80M*); /*---------------------------------------------------------------------------- -*----------------------------------------------------------------------------*/ -#define signF128UI96( a96 ) ((bool) ((uint32_t) (a96)>>31)) -#define expF128UI96( a96 ) ((int32_t) ((a96)>>16) & 0x7FFF) -#define fracF128UI96( a96 ) ((a96) & 0x0000FFFF) -#define packToF128UI96( sign, exp, sig96 ) (((uint32_t) (sign)<<31) + ((uint32_t) (exp)<<16) + (sig96)) + *----------------------------------------------------------------------------*/ +#define signF128UI96(a96) ((bool)((uint32_t)(a96) >> 31)) +#define expF128UI96(a96) ((int32_t)((a96) >> 16) & 0x7FFF) +#define fracF128UI96(a96) ((a96)&0x0000FFFF) +#define packToF128UI96(sign, exp, sig96) (((uint32_t)(sign) << 31) + ((uint32_t)(exp) << 16) + (sig96)) -bool softfloat_isNaNF128M( const uint32_t * ); +bool softfloat_isNaNF128M(const uint32_t*); -bool - softfloat_tryPropagateNaNF128M( - const uint32_t *, const uint32_t *, uint32_t * ); -void softfloat_invalidF128M( uint32_t * ); +bool softfloat_tryPropagateNaNF128M(const uint32_t*, const uint32_t*, uint32_t*); +void softfloat_invalidF128M(uint32_t*); -int softfloat_shiftNormSigF128M( const uint32_t *, uint_fast8_t, uint32_t * ); +int softfloat_shiftNormSigF128M(const uint32_t*, uint_fast8_t, uint32_t*); -void softfloat_roundPackMToF128M( bool, int32_t, uint32_t *, uint32_t * ); -void softfloat_normRoundPackMToF128M( bool, int32_t, uint32_t *, uint32_t * ); +void softfloat_roundPackMToF128M(bool, int32_t, uint32_t*, uint32_t*); +void softfloat_normRoundPackMToF128M(bool, int32_t, uint32_t*, uint32_t*); -void - softfloat_addF128M( const uint32_t *, const uint32_t *, uint32_t *, bool ); -void - softfloat_mulAddF128M( - const uint32_t *, - const uint32_t *, - const uint32_t *, - uint32_t *, - uint_fast8_t - ); +void softfloat_addF128M(const uint32_t*, const uint32_t*, uint32_t*, bool); +void softfloat_mulAddF128M(const uint32_t*, const uint32_t*, const uint32_t*, uint32_t*, uint_fast8_t); #endif #endif - diff --git a/softfloat/source/include/opts-GCC.h b/softfloat/source/include/opts-GCC.h index 18c1523..99a4127 100644 --- a/softfloat/source/include/opts-GCC.h +++ b/softfloat/source/include/opts-GCC.h @@ -39,70 +39,70 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifdef INLINE -#include #include "primitiveTypes.h" +#include #ifdef SOFTFLOAT_BUILTIN_CLZ -INLINE uint_fast8_t softfloat_countLeadingZeros16( uint16_t a ) - { return a ? __builtin_clz( a ) - 16 : 16; } +INLINE uint_fast8_t softfloat_countLeadingZeros16(uint16_t a) { return a ? __builtin_clz(a) - 16 : 16; } #define softfloat_countLeadingZeros16 softfloat_countLeadingZeros16 -INLINE uint_fast8_t softfloat_countLeadingZeros32( uint32_t a ) - { return a ? __builtin_clz( a ) : 32; } +INLINE uint_fast8_t softfloat_countLeadingZeros32(uint32_t a) { return a ? __builtin_clz(a) : 32; } #define softfloat_countLeadingZeros32 softfloat_countLeadingZeros32 -INLINE uint_fast8_t softfloat_countLeadingZeros64( uint64_t a ) - { return a ? __builtin_clzll( a ) : 64; } +INLINE uint_fast8_t softfloat_countLeadingZeros64(uint64_t a) { return a ? __builtin_clzll(a) : 64; } #define softfloat_countLeadingZeros64 softfloat_countLeadingZeros64 #endif #ifdef SOFTFLOAT_INTRINSIC_INT128 -INLINE struct uint128 softfloat_mul64ByShifted32To128( uint64_t a, uint32_t b ) -{ - union { unsigned __int128 ui; struct uint128 s; } uZ; - uZ.ui = (unsigned __int128) a * ((uint_fast64_t) b<<32); +INLINE struct uint128 softfloat_mul64ByShifted32To128(uint64_t a, uint32_t b) { + union { + unsigned __int128 ui; + struct uint128 s; + } uZ; + uZ.ui = (unsigned __int128)a * ((uint_fast64_t)b << 32); return uZ.s; } #define softfloat_mul64ByShifted32To128 softfloat_mul64ByShifted32To128 -INLINE struct uint128 softfloat_mul64To128( uint64_t a, uint64_t b ) -{ - union { unsigned __int128 ui; struct uint128 s; } uZ; - uZ.ui = (unsigned __int128) a * b; +INLINE struct uint128 softfloat_mul64To128(uint64_t a, uint64_t b) { + union { + unsigned __int128 ui; + struct uint128 s; + } uZ; + uZ.ui = (unsigned __int128)a * b; return uZ.s; } #define softfloat_mul64To128 softfloat_mul64To128 INLINE -struct uint128 softfloat_mul128By32( uint64_t a64, uint64_t a0, uint32_t b ) -{ - union { unsigned __int128 ui; struct uint128 s; } uZ; - uZ.ui = ((unsigned __int128) a64<<64 | a0) * b; +struct uint128 softfloat_mul128By32(uint64_t a64, uint64_t a0, uint32_t b) { + union { + unsigned __int128 ui; + struct uint128 s; + } uZ; + uZ.ui = ((unsigned __int128)a64 << 64 | a0) * b; return uZ.s; } #define softfloat_mul128By32 softfloat_mul128By32 INLINE -void - softfloat_mul128To256M( - uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0, uint64_t *zPtr ) -{ +void softfloat_mul128To256M(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0, uint64_t* zPtr) { unsigned __int128 z0, mid1, mid, z128; - z0 = (unsigned __int128) a0 * b0; - mid1 = (unsigned __int128) a64 * b0; - mid = mid1 + (unsigned __int128) a0 * b64; - z128 = (unsigned __int128) a64 * b64; - z128 += (unsigned __int128) (mid < mid1)<<64 | mid>>64; + z0 = (unsigned __int128)a0 * b0; + mid1 = (unsigned __int128)a64 * b0; + mid = mid1 + (unsigned __int128)a0 * b64; + z128 = (unsigned __int128)a64 * b64; + z128 += (unsigned __int128)(mid < mid1) << 64 | mid >> 64; mid <<= 64; z0 += mid; z128 += (z0 < mid); - zPtr[indexWord( 4, 0 )] = z0; - zPtr[indexWord( 4, 1 )] = z0>>64; - zPtr[indexWord( 4, 2 )] = z128; - zPtr[indexWord( 4, 3 )] = z128>>64; + zPtr[indexWord(4, 0)] = z0; + zPtr[indexWord(4, 1)] = z0 >> 64; + zPtr[indexWord(4, 2)] = z128; + zPtr[indexWord(4, 3)] = z128 >> 64; } #define softfloat_mul128To256M softfloat_mul128To256M @@ -111,4 +111,3 @@ void #endif #endif - diff --git a/softfloat/source/include/primitiveTypes.h b/softfloat/source/include/primitiveTypes.h index a4a6dd1..fca21f9 100644 --- a/softfloat/source/include/primitiveTypes.h +++ b/softfloat/source/include/primitiveTypes.h @@ -42,13 +42,27 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifdef SOFTFLOAT_FAST_INT64 #ifdef LITTLEENDIAN -struct uint128 { uint64_t v0, v64; }; -struct uint64_extra { uint64_t extra, v; }; -struct uint128_extra { uint64_t extra; struct uint128 v; }; +struct uint128 { + uint64_t v0, v64; +}; +struct uint64_extra { + uint64_t extra, v; +}; +struct uint128_extra { + uint64_t extra; + struct uint128 v; +}; #else -struct uint128 { uint64_t v64, v0; }; -struct uint64_extra { uint64_t v, extra; }; -struct uint128_extra { struct uint128 v; uint64_t extra; }; +struct uint128 { + uint64_t v64, v0; +}; +struct uint64_extra { + uint64_t v, extra; +}; +struct uint128_extra { + struct uint128 v; + uint64_t extra; +}; #endif #endif @@ -59,27 +73,28 @@ struct uint128_extra { struct uint128 v; uint64_t extra; }; *----------------------------------------------------------------------------*/ #ifdef LITTLEENDIAN #define wordIncr 1 -#define indexWord( total, n ) (n) -#define indexWordHi( total ) ((total) - 1) -#define indexWordLo( total ) 0 -#define indexMultiword( total, m, n ) (n) -#define indexMultiwordHi( total, n ) ((total) - (n)) -#define indexMultiwordLo( total, n ) 0 -#define indexMultiwordHiBut( total, n ) (n) -#define indexMultiwordLoBut( total, n ) 0 -#define INIT_UINTM4( v3, v2, v1, v0 ) { v0, v1, v2, v3 } +#define indexWord(total, n) (n) +#define indexWordHi(total) ((total)-1) +#define indexWordLo(total) 0 +#define indexMultiword(total, m, n) (n) +#define indexMultiwordHi(total, n) ((total) - (n)) +#define indexMultiwordLo(total, n) 0 +#define indexMultiwordHiBut(total, n) (n) +#define indexMultiwordLoBut(total, n) 0 +#define INIT_UINTM4(v3, v2, v1, v0) \ + { v0, v1, v2, v3 } #else #define wordIncr -1 -#define indexWord( total, n ) ((total) - 1 - (n)) -#define indexWordHi( total ) 0 -#define indexWordLo( total ) ((total) - 1) -#define indexMultiword( total, m, n ) ((total) - 1 - (m)) -#define indexMultiwordHi( total, n ) 0 -#define indexMultiwordLo( total, n ) ((total) - (n)) -#define indexMultiwordHiBut( total, n ) 0 -#define indexMultiwordLoBut( total, n ) (n) -#define INIT_UINTM4( v3, v2, v1, v0 ) { v3, v2, v1, v0 } +#define indexWord(total, n) ((total)-1 - (n)) +#define indexWordHi(total) 0 +#define indexWordLo(total) ((total)-1) +#define indexMultiword(total, m, n) ((total)-1 - (m)) +#define indexMultiwordHi(total, n) 0 +#define indexMultiwordLo(total, n) ((total) - (n)) +#define indexMultiwordHiBut(total, n) 0 +#define indexMultiwordLoBut(total, n) (n) +#define INIT_UINTM4(v3, v2, v1, v0) \ + { v3, v2, v1, v0 } #endif #endif - diff --git a/softfloat/source/include/primitives.h b/softfloat/source/include/primitives.h index 863ab45..11967d2 100644 --- a/softfloat/source/include/primitives.h +++ b/softfloat/source/include/primitives.h @@ -37,9 +37,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef primitives_h #define primitives_h 1 +#include "primitiveTypes.h" #include #include -#include "primitiveTypes.h" #ifndef softfloat_shortShiftRightJam64 /*---------------------------------------------------------------------------- @@ -50,10 +50,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *----------------------------------------------------------------------------*/ #if defined INLINE_LEVEL && (2 <= INLINE_LEVEL) INLINE -uint64_t softfloat_shortShiftRightJam64( uint64_t a, uint_fast8_t dist ) - { return a>>dist | ((a & (((uint_fast64_t) 1<> dist | ((a & (((uint_fast64_t)1 << dist) - 1)) != 0); } #else -uint64_t softfloat_shortShiftRightJam64( uint64_t a, uint_fast8_t dist ); +uint64_t softfloat_shortShiftRightJam64(uint64_t a, uint_fast8_t dist); #endif #endif @@ -68,13 +67,11 @@ uint64_t softfloat_shortShiftRightJam64( uint64_t a, uint_fast8_t dist ); | is zero or nonzero. *----------------------------------------------------------------------------*/ #if defined INLINE_LEVEL && (2 <= INLINE_LEVEL) -INLINE uint32_t softfloat_shiftRightJam32( uint32_t a, uint_fast16_t dist ) -{ - return - (dist < 31) ? a>>dist | ((uint32_t) (a<<(-dist & 31)) != 0) : (a != 0); +INLINE uint32_t softfloat_shiftRightJam32(uint32_t a, uint_fast16_t dist) { + return (dist < 31) ? a >> dist | ((uint32_t)(a << (-dist & 31)) != 0) : (a != 0); } #else -uint32_t softfloat_shiftRightJam32( uint32_t a, uint_fast16_t dist ); +uint32_t softfloat_shiftRightJam32(uint32_t a, uint_fast16_t dist); #endif #endif @@ -89,13 +86,11 @@ uint32_t softfloat_shiftRightJam32( uint32_t a, uint_fast16_t dist ); | is zero or nonzero. *----------------------------------------------------------------------------*/ #if defined INLINE_LEVEL && (3 <= INLINE_LEVEL) -INLINE uint64_t softfloat_shiftRightJam64( uint64_t a, uint_fast32_t dist ) -{ - return - (dist < 63) ? a>>dist | ((uint64_t) (a<<(-dist & 63)) != 0) : (a != 0); +INLINE uint64_t softfloat_shiftRightJam64(uint64_t a, uint_fast32_t dist) { + return (dist < 63) ? a >> dist | ((uint64_t)(a << (-dist & 63)) != 0) : (a != 0); } #else -uint64_t softfloat_shiftRightJam64( uint64_t a, uint_fast32_t dist ); +uint64_t softfloat_shiftRightJam64(uint64_t a, uint_fast32_t dist); #endif #endif @@ -112,10 +107,9 @@ extern const uint_least8_t softfloat_countLeadingZeros8[256]; | 'a'. If 'a' is zero, 16 is returned. *----------------------------------------------------------------------------*/ #if defined INLINE_LEVEL && (2 <= INLINE_LEVEL) -INLINE uint_fast8_t softfloat_countLeadingZeros16( uint16_t a ) -{ +INLINE uint_fast8_t softfloat_countLeadingZeros16(uint16_t a) { uint_fast8_t count = 8; - if ( 0x100 <= a ) { + if(0x100 <= a) { count = 0; a >>= 8; } @@ -123,7 +117,7 @@ INLINE uint_fast8_t softfloat_countLeadingZeros16( uint16_t a ) return count; } #else -uint_fast8_t softfloat_countLeadingZeros16( uint16_t a ); +uint_fast8_t softfloat_countLeadingZeros16(uint16_t a); #endif #endif @@ -133,22 +127,21 @@ uint_fast8_t softfloat_countLeadingZeros16( uint16_t a ); | 'a'. If 'a' is zero, 32 is returned. *----------------------------------------------------------------------------*/ #if defined INLINE_LEVEL && (3 <= INLINE_LEVEL) -INLINE uint_fast8_t softfloat_countLeadingZeros32( uint32_t a ) -{ +INLINE uint_fast8_t softfloat_countLeadingZeros32(uint32_t a) { uint_fast8_t count = 0; - if ( a < 0x10000 ) { + if(a < 0x10000) { count = 16; a <<= 16; } - if ( a < 0x1000000 ) { + if(a < 0x1000000) { count += 8; a <<= 8; } - count += softfloat_countLeadingZeros8[a>>24]; + count += softfloat_countLeadingZeros8[a >> 24]; return count; } #else -uint_fast8_t softfloat_countLeadingZeros32( uint32_t a ); +uint_fast8_t softfloat_countLeadingZeros32(uint32_t a); #endif #endif @@ -157,7 +150,7 @@ uint_fast8_t softfloat_countLeadingZeros32( uint32_t a ); | Returns the number of leading 0 bits before the most-significant 1 bit of | 'a'. If 'a' is zero, 64 is returned. *----------------------------------------------------------------------------*/ -uint_fast8_t softfloat_countLeadingZeros64( uint64_t a ); +uint_fast8_t softfloat_countLeadingZeros64(uint64_t a); #endif extern const uint16_t softfloat_approxRecip_1k0s[16]; @@ -176,9 +169,9 @@ extern const uint16_t softfloat_approxRecip_1k1s[16]; | (units in the last place). *----------------------------------------------------------------------------*/ #ifdef SOFTFLOAT_FAST_DIV64TO32 -#define softfloat_approxRecip32_1( a ) ((uint32_t) (UINT64_C( 0x7FFFFFFFFFFFFFFF ) / (uint32_t) (a))) +#define softfloat_approxRecip32_1(a) ((uint32_t)(UINT64_C(0x7FFFFFFFFFFFFFFF) / (uint32_t)(a))) #else -uint32_t softfloat_approxRecip32_1( uint32_t a ); +uint32_t softfloat_approxRecip32_1(uint32_t a); #endif #endif @@ -204,7 +197,7 @@ extern const uint16_t softfloat_approxRecipSqrt_1k1s[16]; | returned is also always within the range 0.5 to 1; thus, the most- | significant bit of the result is always set. *----------------------------------------------------------------------------*/ -uint32_t softfloat_approxRecipSqrt32_1( unsigned int oddExpA, uint32_t a ); +uint32_t softfloat_approxRecipSqrt32_1(unsigned int oddExpA, uint32_t a); #endif #ifdef SOFTFLOAT_FAST_INT64 @@ -222,10 +215,9 @@ uint32_t softfloat_approxRecipSqrt32_1( unsigned int oddExpA, uint32_t a ); *----------------------------------------------------------------------------*/ #if defined INLINE_LEVEL && (1 <= INLINE_LEVEL) INLINE -bool softfloat_eq128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ) - { return (a64 == b64) && (a0 == b0); } +bool softfloat_eq128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0) { return (a64 == b64) && (a0 == b0); } #else -bool softfloat_eq128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ); +bool softfloat_eq128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0); #endif #endif @@ -237,10 +229,9 @@ bool softfloat_eq128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ); *----------------------------------------------------------------------------*/ #if defined INLINE_LEVEL && (2 <= INLINE_LEVEL) INLINE -bool softfloat_le128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ) - { return (a64 < b64) || ((a64 == b64) && (a0 <= b0)); } +bool softfloat_le128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0) { return (a64 < b64) || ((a64 == b64) && (a0 <= b0)); } #else -bool softfloat_le128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ); +bool softfloat_le128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0); #endif #endif @@ -252,10 +243,9 @@ bool softfloat_le128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ); *----------------------------------------------------------------------------*/ #if defined INLINE_LEVEL && (2 <= INLINE_LEVEL) INLINE -bool softfloat_lt128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ) - { return (a64 < b64) || ((a64 == b64) && (a0 < b0)); } +bool softfloat_lt128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0) { return (a64 < b64) || ((a64 == b64) && (a0 < b0)); } #else -bool softfloat_lt128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ); +bool softfloat_lt128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0); #endif #endif @@ -266,17 +256,14 @@ bool softfloat_lt128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ); *----------------------------------------------------------------------------*/ #if defined INLINE_LEVEL && (2 <= INLINE_LEVEL) INLINE -struct uint128 - softfloat_shortShiftLeft128( uint64_t a64, uint64_t a0, uint_fast8_t dist ) -{ +struct uint128 softfloat_shortShiftLeft128(uint64_t a64, uint64_t a0, uint_fast8_t dist) { struct uint128 z; - z.v64 = a64<>(-dist & 63); - z.v0 = a0<> (-dist & 63); + z.v0 = a0 << dist; return z; } #else -struct uint128 - softfloat_shortShiftLeft128( uint64_t a64, uint64_t a0, uint_fast8_t dist ); +struct uint128 softfloat_shortShiftLeft128(uint64_t a64, uint64_t a0, uint_fast8_t dist); #endif #endif @@ -287,17 +274,14 @@ struct uint128 *----------------------------------------------------------------------------*/ #if defined INLINE_LEVEL && (2 <= INLINE_LEVEL) INLINE -struct uint128 - softfloat_shortShiftRight128( uint64_t a64, uint64_t a0, uint_fast8_t dist ) -{ +struct uint128 softfloat_shortShiftRight128(uint64_t a64, uint64_t a0, uint_fast8_t dist) { struct uint128 z; - z.v64 = a64>>dist; - z.v0 = a64<<(-dist & 63) | a0>>dist; + z.v64 = a64 >> dist; + z.v0 = a64 << (-dist & 63) | a0 >> dist; return z; } #else -struct uint128 - softfloat_shortShiftRight128( uint64_t a64, uint64_t a0, uint_fast8_t dist ); +struct uint128 softfloat_shortShiftRight128(uint64_t a64, uint64_t a0, uint_fast8_t dist); #endif #endif @@ -308,19 +292,14 @@ struct uint128 *----------------------------------------------------------------------------*/ #if defined INLINE_LEVEL && (2 <= INLINE_LEVEL) INLINE -struct uint64_extra - softfloat_shortShiftRightJam64Extra( - uint64_t a, uint64_t extra, uint_fast8_t dist ) -{ +struct uint64_extra softfloat_shortShiftRightJam64Extra(uint64_t a, uint64_t extra, uint_fast8_t dist) { struct uint64_extra z; - z.v = a>>dist; - z.extra = a<<(-dist & 63) | (extra != 0); + z.v = a >> dist; + z.extra = a << (-dist & 63) | (extra != 0); return z; } #else -struct uint64_extra - softfloat_shortShiftRightJam64Extra( - uint64_t a, uint64_t extra, uint_fast8_t dist ); +struct uint64_extra softfloat_shortShiftRightJam64Extra(uint64_t a, uint64_t extra, uint_fast8_t dist); #endif #endif @@ -334,22 +313,15 @@ struct uint64_extra *----------------------------------------------------------------------------*/ #if defined INLINE_LEVEL && (3 <= INLINE_LEVEL) INLINE -struct uint128 - softfloat_shortShiftRightJam128( - uint64_t a64, uint64_t a0, uint_fast8_t dist ) -{ +struct uint128 softfloat_shortShiftRightJam128(uint64_t a64, uint64_t a0, uint_fast8_t dist) { uint_fast8_t negDist = -dist; struct uint128 z; - z.v64 = a64>>dist; - z.v0 = - a64<<(negDist & 63) | a0>>dist - | ((uint64_t) (a0<<(negDist & 63)) != 0); + z.v64 = a64 >> dist; + z.v0 = a64 << (negDist & 63) | a0 >> dist | ((uint64_t)(a0 << (negDist & 63)) != 0); return z; } #else -struct uint128 - softfloat_shortShiftRightJam128( - uint64_t a64, uint64_t a0, uint_fast8_t dist ); +struct uint128 softfloat_shortShiftRightJam128(uint64_t a64, uint64_t a0, uint_fast8_t dist); #endif #endif @@ -360,21 +332,16 @@ struct uint128 *----------------------------------------------------------------------------*/ #if defined INLINE_LEVEL && (3 <= INLINE_LEVEL) INLINE -struct uint128_extra - softfloat_shortShiftRightJam128Extra( - uint64_t a64, uint64_t a0, uint64_t extra, uint_fast8_t dist ) -{ +struct uint128_extra softfloat_shortShiftRightJam128Extra(uint64_t a64, uint64_t a0, uint64_t extra, uint_fast8_t dist) { uint_fast8_t negDist = -dist; struct uint128_extra z; - z.v.v64 = a64>>dist; - z.v.v0 = a64<<(negDist & 63) | a0>>dist; - z.extra = a0<<(negDist & 63) | (extra != 0); + z.v.v64 = a64 >> dist; + z.v.v0 = a64 << (negDist & 63) | a0 >> dist; + z.extra = a0 << (negDist & 63) | (extra != 0); return z; } #else -struct uint128_extra - softfloat_shortShiftRightJam128Extra( - uint64_t a64, uint64_t a0, uint64_t extra, uint_fast8_t dist ); +struct uint128_extra softfloat_shortShiftRightJam128Extra(uint64_t a64, uint64_t a0, uint64_t extra, uint_fast8_t dist); #endif #endif @@ -397,14 +364,11 @@ struct uint128_extra *----------------------------------------------------------------------------*/ #if defined INLINE_LEVEL && (4 <= INLINE_LEVEL) INLINE -struct uint64_extra - softfloat_shiftRightJam64Extra( - uint64_t a, uint64_t extra, uint_fast32_t dist ) -{ +struct uint64_extra softfloat_shiftRightJam64Extra(uint64_t a, uint64_t extra, uint_fast32_t dist) { struct uint64_extra z; - if ( dist < 64 ) { - z.v = a>>dist; - z.extra = a<<(-dist & 63); + if(dist < 64) { + z.v = a >> dist; + z.extra = a << (-dist & 63); } else { z.v = 0; z.extra = (dist == 64) ? a : (a != 0); @@ -413,9 +377,7 @@ struct uint64_extra return z; } #else -struct uint64_extra - softfloat_shiftRightJam64Extra( - uint64_t a, uint64_t extra, uint_fast32_t dist ); +struct uint64_extra softfloat_shiftRightJam64Extra(uint64_t a, uint64_t extra, uint_fast32_t dist); #endif #endif @@ -430,8 +392,7 @@ struct uint64_extra | greater than 128, the result will be either 0 or 1, depending on whether the | original 128 bits are all zeros. *----------------------------------------------------------------------------*/ -struct uint128 - softfloat_shiftRightJam128( uint64_t a64, uint64_t a0, uint_fast32_t dist ); +struct uint128 softfloat_shiftRightJam128(uint64_t a64, uint64_t a0, uint_fast32_t dist); #endif #ifndef softfloat_shiftRightJam128Extra @@ -452,9 +413,7 @@ struct uint128 | is modified as described above and returned in the 'extra' field of the | result.) *----------------------------------------------------------------------------*/ -struct uint128_extra - softfloat_shiftRightJam128Extra( - uint64_t a64, uint64_t a0, uint64_t extra, uint_fast32_t dist ); +struct uint128_extra softfloat_shiftRightJam128Extra(uint64_t a64, uint64_t a0, uint64_t extra, uint_fast32_t dist); #endif #ifndef softfloat_shiftRightJam256M @@ -470,9 +429,7 @@ struct uint128_extra | is greater than 256, the stored result will be either 0 or 1, depending on | whether the original 256 bits are all zeros. *----------------------------------------------------------------------------*/ -void - softfloat_shiftRightJam256M( - const uint64_t *aPtr, uint_fast32_t dist, uint64_t *zPtr ); +void softfloat_shiftRightJam256M(const uint64_t* aPtr, uint_fast32_t dist, uint64_t* zPtr); #endif #ifndef softfloat_add128 @@ -483,17 +440,14 @@ void *----------------------------------------------------------------------------*/ #if defined INLINE_LEVEL && (2 <= INLINE_LEVEL) INLINE -struct uint128 - softfloat_add128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ) -{ +struct uint128 softfloat_add128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0) { struct uint128 z; z.v0 = a0 + b0; z.v64 = a64 + b64 + (z.v0 < a0); return z; } #else -struct uint128 - softfloat_add128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ); +struct uint128 softfloat_add128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0); #endif #endif @@ -505,9 +459,7 @@ struct uint128 | an array of four 64-bit elements that concatenate in the platform's normal | endian order to form a 256-bit integer. *----------------------------------------------------------------------------*/ -void - softfloat_add256M( - const uint64_t *aPtr, const uint64_t *bPtr, uint64_t *zPtr ); +void softfloat_add256M(const uint64_t* aPtr, const uint64_t* bPtr, uint64_t* zPtr); #endif #ifndef softfloat_sub128 @@ -518,9 +470,7 @@ void *----------------------------------------------------------------------------*/ #if defined INLINE_LEVEL && (2 <= INLINE_LEVEL) INLINE -struct uint128 - softfloat_sub128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ) -{ +struct uint128 softfloat_sub128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0) { struct uint128 z; z.v0 = a0 - b0; z.v64 = a64 - b64; @@ -528,8 +478,7 @@ struct uint128 return z; } #else -struct uint128 - softfloat_sub128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ); +struct uint128 softfloat_sub128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0); #endif #endif @@ -542,9 +491,7 @@ struct uint128 | 64-bit elements that concatenate in the platform's normal endian order to | form a 256-bit integer. *----------------------------------------------------------------------------*/ -void - softfloat_sub256M( - const uint64_t *aPtr, const uint64_t *bPtr, uint64_t *zPtr ); +void softfloat_sub256M(const uint64_t* aPtr, const uint64_t* bPtr, uint64_t* zPtr); #endif #ifndef softfloat_mul64ByShifted32To128 @@ -552,17 +499,16 @@ void | Returns the 128-bit product of 'a', 'b', and 2^32. *----------------------------------------------------------------------------*/ #if defined INLINE_LEVEL && (3 <= INLINE_LEVEL) -INLINE struct uint128 softfloat_mul64ByShifted32To128( uint64_t a, uint32_t b ) -{ +INLINE struct uint128 softfloat_mul64ByShifted32To128(uint64_t a, uint32_t b) { uint_fast64_t mid; struct uint128 z; - mid = (uint_fast64_t) (uint32_t) a * b; - z.v0 = mid<<32; - z.v64 = (uint_fast64_t) (uint32_t) (a>>32) * b + (mid>>32); + mid = (uint_fast64_t)(uint32_t)a * b; + z.v0 = mid << 32; + z.v64 = (uint_fast64_t)(uint32_t)(a >> 32) * b + (mid >> 32); return z; } #else -struct uint128 softfloat_mul64ByShifted32To128( uint64_t a, uint32_t b ); +struct uint128 softfloat_mul64ByShifted32To128(uint64_t a, uint32_t b); #endif #endif @@ -570,7 +516,7 @@ struct uint128 softfloat_mul64ByShifted32To128( uint64_t a, uint32_t b ); /*---------------------------------------------------------------------------- | Returns the 128-bit product of 'a' and 'b'. *----------------------------------------------------------------------------*/ -struct uint128 softfloat_mul64To128( uint64_t a, uint64_t b ); +struct uint128 softfloat_mul64To128(uint64_t a, uint64_t b); #endif #ifndef softfloat_mul128By32 @@ -581,19 +527,18 @@ struct uint128 softfloat_mul64To128( uint64_t a, uint64_t b ); *----------------------------------------------------------------------------*/ #if defined INLINE_LEVEL && (4 <= INLINE_LEVEL) INLINE -struct uint128 softfloat_mul128By32( uint64_t a64, uint64_t a0, uint32_t b ) -{ +struct uint128 softfloat_mul128By32(uint64_t a64, uint64_t a0, uint32_t b) { struct uint128 z; uint_fast64_t mid; uint_fast32_t carry; z.v0 = a0 * b; - mid = (uint_fast64_t) (uint32_t) (a0>>32) * b; - carry = (uint32_t) ((uint_fast32_t) (z.v0>>32) - (uint_fast32_t) mid); - z.v64 = a64 * b + (uint_fast32_t) ((mid + carry)>>32); + mid = (uint_fast64_t)(uint32_t)(a0 >> 32) * b; + carry = (uint32_t)((uint_fast32_t)(z.v0 >> 32) - (uint_fast32_t)mid); + z.v64 = a64 * b + (uint_fast32_t)((mid + carry) >> 32); return z; } #else -struct uint128 softfloat_mul128By32( uint64_t a64, uint64_t a0, uint32_t b ); +struct uint128 softfloat_mul128By32(uint64_t a64, uint64_t a0, uint32_t b); #endif #endif @@ -605,9 +550,7 @@ struct uint128 softfloat_mul128By32( uint64_t a64, uint64_t a0, uint32_t b ); | Argument 'zPtr' points to an array of four 64-bit elements that concatenate | in the platform's normal endian order to form a 256-bit integer. *----------------------------------------------------------------------------*/ -void - softfloat_mul128To256M( - uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0, uint64_t *zPtr ); +void softfloat_mul128To256M(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0, uint64_t* zPtr); #endif #else @@ -626,7 +569,7 @@ void | Each of 'aPtr' and 'bPtr' points to an array of three 32-bit elements that | concatenate in the platform's normal endian order to form a 96-bit integer. *----------------------------------------------------------------------------*/ -int_fast8_t softfloat_compare96M( const uint32_t *aPtr, const uint32_t *bPtr ); +int_fast8_t softfloat_compare96M(const uint32_t* aPtr, const uint32_t* bPtr); #endif #ifndef softfloat_compare128M @@ -638,8 +581,7 @@ int_fast8_t softfloat_compare96M( const uint32_t *aPtr, const uint32_t *bPtr ); | Each of 'aPtr' and 'bPtr' points to an array of four 32-bit elements that | concatenate in the platform's normal endian order to form a 128-bit integer. *----------------------------------------------------------------------------*/ -int_fast8_t - softfloat_compare128M( const uint32_t *aPtr, const uint32_t *bPtr ); +int_fast8_t softfloat_compare128M(const uint32_t* aPtr, const uint32_t* bPtr); #endif #ifndef softfloat_shortShiftLeft64To96M @@ -652,19 +594,14 @@ int_fast8_t *----------------------------------------------------------------------------*/ #if defined INLINE_LEVEL && (2 <= INLINE_LEVEL) INLINE -void - softfloat_shortShiftLeft64To96M( - uint64_t a, uint_fast8_t dist, uint32_t *zPtr ) -{ - zPtr[indexWord( 3, 0 )] = (uint32_t) a<>= 32 - dist; - zPtr[indexWord( 3, 2 )] = a>>32; - zPtr[indexWord( 3, 1 )] = a; + zPtr[indexWord(3, 2)] = a >> 32; + zPtr[indexWord(3, 1)] = a; } #else -void - softfloat_shortShiftLeft64To96M( - uint64_t a, uint_fast8_t dist, uint32_t *zPtr ); +void softfloat_shortShiftLeft64To96M(uint64_t a, uint_fast8_t dist, uint32_t* zPtr); #endif #endif @@ -678,13 +615,7 @@ void | that concatenate in the platform's normal endian order to form an N-bit | integer. *----------------------------------------------------------------------------*/ -void - softfloat_shortShiftLeftM( - uint_fast8_t size_words, - const uint32_t *aPtr, - uint_fast8_t dist, - uint32_t *zPtr - ); +void softfloat_shortShiftLeftM(uint_fast8_t size_words, const uint32_t* aPtr, uint_fast8_t dist, uint32_t* zPtr); #endif #ifndef softfloat_shortShiftLeft96M @@ -692,7 +623,7 @@ void | This function or macro is the same as 'softfloat_shortShiftLeftM' with | 'size_words' = 3 (N = 96). *----------------------------------------------------------------------------*/ -#define softfloat_shortShiftLeft96M( aPtr, dist, zPtr ) softfloat_shortShiftLeftM( 3, aPtr, dist, zPtr ) +#define softfloat_shortShiftLeft96M(aPtr, dist, zPtr) softfloat_shortShiftLeftM(3, aPtr, dist, zPtr) #endif #ifndef softfloat_shortShiftLeft128M @@ -700,7 +631,7 @@ void | This function or macro is the same as 'softfloat_shortShiftLeftM' with | 'size_words' = 4 (N = 128). *----------------------------------------------------------------------------*/ -#define softfloat_shortShiftLeft128M( aPtr, dist, zPtr ) softfloat_shortShiftLeftM( 4, aPtr, dist, zPtr ) +#define softfloat_shortShiftLeft128M(aPtr, dist, zPtr) softfloat_shortShiftLeftM(4, aPtr, dist, zPtr) #endif #ifndef softfloat_shortShiftLeft160M @@ -708,7 +639,7 @@ void | This function or macro is the same as 'softfloat_shortShiftLeftM' with | 'size_words' = 5 (N = 160). *----------------------------------------------------------------------------*/ -#define softfloat_shortShiftLeft160M( aPtr, dist, zPtr ) softfloat_shortShiftLeftM( 5, aPtr, dist, zPtr ) +#define softfloat_shortShiftLeft160M(aPtr, dist, zPtr) softfloat_shortShiftLeftM(5, aPtr, dist, zPtr) #endif #ifndef softfloat_shiftLeftM @@ -722,13 +653,7 @@ void | The value of 'dist' can be arbitrarily large. In particular, if 'dist' is | greater than N, the stored result will be 0. *----------------------------------------------------------------------------*/ -void - softfloat_shiftLeftM( - uint_fast8_t size_words, - const uint32_t *aPtr, - uint32_t dist, - uint32_t *zPtr - ); +void softfloat_shiftLeftM(uint_fast8_t size_words, const uint32_t* aPtr, uint32_t dist, uint32_t* zPtr); #endif #ifndef softfloat_shiftLeft96M @@ -736,7 +661,7 @@ void | This function or macro is the same as 'softfloat_shiftLeftM' with | 'size_words' = 3 (N = 96). *----------------------------------------------------------------------------*/ -#define softfloat_shiftLeft96M( aPtr, dist, zPtr ) softfloat_shiftLeftM( 3, aPtr, dist, zPtr ) +#define softfloat_shiftLeft96M(aPtr, dist, zPtr) softfloat_shiftLeftM(3, aPtr, dist, zPtr) #endif #ifndef softfloat_shiftLeft128M @@ -744,7 +669,7 @@ void | This function or macro is the same as 'softfloat_shiftLeftM' with | 'size_words' = 4 (N = 128). *----------------------------------------------------------------------------*/ -#define softfloat_shiftLeft128M( aPtr, dist, zPtr ) softfloat_shiftLeftM( 4, aPtr, dist, zPtr ) +#define softfloat_shiftLeft128M(aPtr, dist, zPtr) softfloat_shiftLeftM(4, aPtr, dist, zPtr) #endif #ifndef softfloat_shiftLeft160M @@ -752,7 +677,7 @@ void | This function or macro is the same as 'softfloat_shiftLeftM' with | 'size_words' = 5 (N = 160). *----------------------------------------------------------------------------*/ -#define softfloat_shiftLeft160M( aPtr, dist, zPtr ) softfloat_shiftLeftM( 5, aPtr, dist, zPtr ) +#define softfloat_shiftLeft160M(aPtr, dist, zPtr) softfloat_shiftLeftM(5, aPtr, dist, zPtr) #endif #ifndef softfloat_shortShiftRightM @@ -765,13 +690,7 @@ void | that concatenate in the platform's normal endian order to form an N-bit | integer. *----------------------------------------------------------------------------*/ -void - softfloat_shortShiftRightM( - uint_fast8_t size_words, - const uint32_t *aPtr, - uint_fast8_t dist, - uint32_t *zPtr - ); +void softfloat_shortShiftRightM(uint_fast8_t size_words, const uint32_t* aPtr, uint_fast8_t dist, uint32_t* zPtr); #endif #ifndef softfloat_shortShiftRight128M @@ -779,7 +698,7 @@ void | This function or macro is the same as 'softfloat_shortShiftRightM' with | 'size_words' = 4 (N = 128). *----------------------------------------------------------------------------*/ -#define softfloat_shortShiftRight128M( aPtr, dist, zPtr ) softfloat_shortShiftRightM( 4, aPtr, dist, zPtr ) +#define softfloat_shortShiftRight128M(aPtr, dist, zPtr) softfloat_shortShiftRightM(4, aPtr, dist, zPtr) #endif #ifndef softfloat_shortShiftRight160M @@ -787,7 +706,7 @@ void | This function or macro is the same as 'softfloat_shortShiftRightM' with | 'size_words' = 5 (N = 160). *----------------------------------------------------------------------------*/ -#define softfloat_shortShiftRight160M( aPtr, dist, zPtr ) softfloat_shortShiftRightM( 5, aPtr, dist, zPtr ) +#define softfloat_shortShiftRight160M(aPtr, dist, zPtr) softfloat_shortShiftRightM(5, aPtr, dist, zPtr) #endif #ifndef softfloat_shortShiftRightJamM @@ -801,9 +720,7 @@ void | to a 'size_words'-long array of 32-bit elements that concatenate in the | platform's normal endian order to form an N-bit integer. *----------------------------------------------------------------------------*/ -void - softfloat_shortShiftRightJamM( - uint_fast8_t, const uint32_t *, uint_fast8_t, uint32_t * ); +void softfloat_shortShiftRightJamM(uint_fast8_t, const uint32_t*, uint_fast8_t, uint32_t*); #endif #ifndef softfloat_shortShiftRightJam160M @@ -811,7 +728,7 @@ void | This function or macro is the same as 'softfloat_shortShiftRightJamM' with | 'size_words' = 5 (N = 160). *----------------------------------------------------------------------------*/ -#define softfloat_shortShiftRightJam160M( aPtr, dist, zPtr ) softfloat_shortShiftRightJamM( 5, aPtr, dist, zPtr ) +#define softfloat_shortShiftRightJam160M(aPtr, dist, zPtr) softfloat_shortShiftRightJamM(5, aPtr, dist, zPtr) #endif #ifndef softfloat_shiftRightM @@ -825,13 +742,7 @@ void | The value of 'dist' can be arbitrarily large. In particular, if 'dist' is | greater than N, the stored result will be 0. *----------------------------------------------------------------------------*/ -void - softfloat_shiftRightM( - uint_fast8_t size_words, - const uint32_t *aPtr, - uint32_t dist, - uint32_t *zPtr - ); +void softfloat_shiftRightM(uint_fast8_t size_words, const uint32_t* aPtr, uint32_t dist, uint32_t* zPtr); #endif #ifndef softfloat_shiftRight96M @@ -839,7 +750,7 @@ void | This function or macro is the same as 'softfloat_shiftRightM' with | 'size_words' = 3 (N = 96). *----------------------------------------------------------------------------*/ -#define softfloat_shiftRight96M( aPtr, dist, zPtr ) softfloat_shiftRightM( 3, aPtr, dist, zPtr ) +#define softfloat_shiftRight96M(aPtr, dist, zPtr) softfloat_shiftRightM(3, aPtr, dist, zPtr) #endif #ifndef softfloat_shiftRightJamM @@ -856,13 +767,7 @@ void | is greater than N, the stored result will be either 0 or 1, depending on | whether the original N bits are all zeros. *----------------------------------------------------------------------------*/ -void - softfloat_shiftRightJamM( - uint_fast8_t size_words, - const uint32_t *aPtr, - uint32_t dist, - uint32_t *zPtr - ); +void softfloat_shiftRightJamM(uint_fast8_t size_words, const uint32_t* aPtr, uint32_t dist, uint32_t* zPtr); #endif #ifndef softfloat_shiftRightJam96M @@ -870,7 +775,7 @@ void | This function or macro is the same as 'softfloat_shiftRightJamM' with | 'size_words' = 3 (N = 96). *----------------------------------------------------------------------------*/ -#define softfloat_shiftRightJam96M( aPtr, dist, zPtr ) softfloat_shiftRightJamM( 3, aPtr, dist, zPtr ) +#define softfloat_shiftRightJam96M(aPtr, dist, zPtr) softfloat_shiftRightJamM(3, aPtr, dist, zPtr) #endif #ifndef softfloat_shiftRightJam128M @@ -878,7 +783,7 @@ void | This function or macro is the same as 'softfloat_shiftRightJamM' with | 'size_words' = 4 (N = 128). *----------------------------------------------------------------------------*/ -#define softfloat_shiftRightJam128M( aPtr, dist, zPtr ) softfloat_shiftRightJamM( 4, aPtr, dist, zPtr ) +#define softfloat_shiftRightJam128M(aPtr, dist, zPtr) softfloat_shiftRightJamM(4, aPtr, dist, zPtr) #endif #ifndef softfloat_shiftRightJam160M @@ -886,7 +791,7 @@ void | This function or macro is the same as 'softfloat_shiftRightJamM' with | 'size_words' = 5 (N = 160). *----------------------------------------------------------------------------*/ -#define softfloat_shiftRightJam160M( aPtr, dist, zPtr ) softfloat_shiftRightJamM( 5, aPtr, dist, zPtr ) +#define softfloat_shiftRightJam160M(aPtr, dist, zPtr) softfloat_shiftRightJamM(5, aPtr, dist, zPtr) #endif #ifndef softfloat_addM @@ -898,13 +803,7 @@ void | elements that concatenate in the platform's normal endian order to form an | N-bit integer. *----------------------------------------------------------------------------*/ -void - softfloat_addM( - uint_fast8_t size_words, - const uint32_t *aPtr, - const uint32_t *bPtr, - uint32_t *zPtr - ); +void softfloat_addM(uint_fast8_t size_words, const uint32_t* aPtr, const uint32_t* bPtr, uint32_t* zPtr); #endif #ifndef softfloat_add96M @@ -912,7 +811,7 @@ void | This function or macro is the same as 'softfloat_addM' with 'size_words' | = 3 (N = 96). *----------------------------------------------------------------------------*/ -#define softfloat_add96M( aPtr, bPtr, zPtr ) softfloat_addM( 3, aPtr, bPtr, zPtr ) +#define softfloat_add96M(aPtr, bPtr, zPtr) softfloat_addM(3, aPtr, bPtr, zPtr) #endif #ifndef softfloat_add128M @@ -920,7 +819,7 @@ void | This function or macro is the same as 'softfloat_addM' with 'size_words' | = 4 (N = 128). *----------------------------------------------------------------------------*/ -#define softfloat_add128M( aPtr, bPtr, zPtr ) softfloat_addM( 4, aPtr, bPtr, zPtr ) +#define softfloat_add128M(aPtr, bPtr, zPtr) softfloat_addM(4, aPtr, bPtr, zPtr) #endif #ifndef softfloat_add160M @@ -928,7 +827,7 @@ void | This function or macro is the same as 'softfloat_addM' with 'size_words' | = 5 (N = 160). *----------------------------------------------------------------------------*/ -#define softfloat_add160M( aPtr, bPtr, zPtr ) softfloat_addM( 5, aPtr, bPtr, zPtr ) +#define softfloat_add160M(aPtr, bPtr, zPtr) softfloat_addM(5, aPtr, bPtr, zPtr) #endif #ifndef softfloat_addCarryM @@ -940,14 +839,7 @@ void | points to a 'size_words'-long array of 32-bit elements that concatenate in | the platform's normal endian order to form an N-bit integer. *----------------------------------------------------------------------------*/ -uint_fast8_t - softfloat_addCarryM( - uint_fast8_t size_words, - const uint32_t *aPtr, - const uint32_t *bPtr, - uint_fast8_t carry, - uint32_t *zPtr - ); +uint_fast8_t softfloat_addCarryM(uint_fast8_t size_words, const uint32_t* aPtr, const uint32_t* bPtr, uint_fast8_t carry, uint32_t* zPtr); #endif #ifndef softfloat_addComplCarryM @@ -956,14 +848,8 @@ uint_fast8_t | the value of the unsigned integer pointed to by 'bPtr' is bit-wise completed | before the addition. *----------------------------------------------------------------------------*/ -uint_fast8_t - softfloat_addComplCarryM( - uint_fast8_t size_words, - const uint32_t *aPtr, - const uint32_t *bPtr, - uint_fast8_t carry, - uint32_t *zPtr - ); +uint_fast8_t softfloat_addComplCarryM(uint_fast8_t size_words, const uint32_t* aPtr, const uint32_t* bPtr, uint_fast8_t carry, + uint32_t* zPtr); #endif #ifndef softfloat_addComplCarry96M @@ -971,7 +857,7 @@ uint_fast8_t | This function or macro is the same as 'softfloat_addComplCarryM' with | 'size_words' = 3 (N = 96). *----------------------------------------------------------------------------*/ -#define softfloat_addComplCarry96M( aPtr, bPtr, carry, zPtr ) softfloat_addComplCarryM( 3, aPtr, bPtr, carry, zPtr ) +#define softfloat_addComplCarry96M(aPtr, bPtr, carry, zPtr) softfloat_addComplCarryM(3, aPtr, bPtr, carry, zPtr) #endif #ifndef softfloat_negXM @@ -981,7 +867,7 @@ uint_fast8_t | points to a 'size_words'-long array of 32-bit elements that concatenate in | the platform's normal endian order to form an N-bit integer. *----------------------------------------------------------------------------*/ -void softfloat_negXM( uint_fast8_t size_words, uint32_t *zPtr ); +void softfloat_negXM(uint_fast8_t size_words, uint32_t* zPtr); #endif #ifndef softfloat_negX96M @@ -989,7 +875,7 @@ void softfloat_negXM( uint_fast8_t size_words, uint32_t *zPtr ); | This function or macro is the same as 'softfloat_negXM' with 'size_words' | = 3 (N = 96). *----------------------------------------------------------------------------*/ -#define softfloat_negX96M( zPtr ) softfloat_negXM( 3, zPtr ) +#define softfloat_negX96M(zPtr) softfloat_negXM(3, zPtr) #endif #ifndef softfloat_negX128M @@ -997,7 +883,7 @@ void softfloat_negXM( uint_fast8_t size_words, uint32_t *zPtr ); | This function or macro is the same as 'softfloat_negXM' with 'size_words' | = 4 (N = 128). *----------------------------------------------------------------------------*/ -#define softfloat_negX128M( zPtr ) softfloat_negXM( 4, zPtr ) +#define softfloat_negX128M(zPtr) softfloat_negXM(4, zPtr) #endif #ifndef softfloat_negX160M @@ -1005,7 +891,7 @@ void softfloat_negXM( uint_fast8_t size_words, uint32_t *zPtr ); | This function or macro is the same as 'softfloat_negXM' with 'size_words' | = 5 (N = 160). *----------------------------------------------------------------------------*/ -#define softfloat_negX160M( zPtr ) softfloat_negXM( 5, zPtr ) +#define softfloat_negX160M(zPtr) softfloat_negXM(5, zPtr) #endif #ifndef softfloat_negX256M @@ -1013,7 +899,7 @@ void softfloat_negXM( uint_fast8_t size_words, uint32_t *zPtr ); | This function or macro is the same as 'softfloat_negXM' with 'size_words' | = 8 (N = 256). *----------------------------------------------------------------------------*/ -#define softfloat_negX256M( zPtr ) softfloat_negXM( 8, zPtr ) +#define softfloat_negX256M(zPtr) softfloat_negXM(8, zPtr) #endif #ifndef softfloat_sub1XM @@ -1024,7 +910,7 @@ void softfloat_negXM( uint_fast8_t size_words, uint32_t *zPtr ); | elements that concatenate in the platform's normal endian order to form an | N-bit integer. *----------------------------------------------------------------------------*/ -void softfloat_sub1XM( uint_fast8_t size_words, uint32_t *zPtr ); +void softfloat_sub1XM(uint_fast8_t size_words, uint32_t* zPtr); #endif #ifndef softfloat_sub1X96M @@ -1032,7 +918,7 @@ void softfloat_sub1XM( uint_fast8_t size_words, uint32_t *zPtr ); | This function or macro is the same as 'softfloat_sub1XM' with 'size_words' | = 3 (N = 96). *----------------------------------------------------------------------------*/ -#define softfloat_sub1X96M( zPtr ) softfloat_sub1XM( 3, zPtr ) +#define softfloat_sub1X96M(zPtr) softfloat_sub1XM(3, zPtr) #endif #ifndef softfloat_sub1X160M @@ -1040,7 +926,7 @@ void softfloat_sub1XM( uint_fast8_t size_words, uint32_t *zPtr ); | This function or macro is the same as 'softfloat_sub1XM' with 'size_words' | = 5 (N = 160). *----------------------------------------------------------------------------*/ -#define softfloat_sub1X160M( zPtr ) softfloat_sub1XM( 5, zPtr ) +#define softfloat_sub1X160M(zPtr) softfloat_sub1XM(5, zPtr) #endif #ifndef softfloat_subM @@ -1052,13 +938,7 @@ void softfloat_sub1XM( uint_fast8_t size_words, uint32_t *zPtr ); | array of 32-bit elements that concatenate in the platform's normal endian | order to form an N-bit integer. *----------------------------------------------------------------------------*/ -void - softfloat_subM( - uint_fast8_t size_words, - const uint32_t *aPtr, - const uint32_t *bPtr, - uint32_t *zPtr - ); +void softfloat_subM(uint_fast8_t size_words, const uint32_t* aPtr, const uint32_t* bPtr, uint32_t* zPtr); #endif #ifndef softfloat_sub96M @@ -1066,7 +946,7 @@ void | This function or macro is the same as 'softfloat_subM' with 'size_words' | = 3 (N = 96). *----------------------------------------------------------------------------*/ -#define softfloat_sub96M( aPtr, bPtr, zPtr ) softfloat_subM( 3, aPtr, bPtr, zPtr ) +#define softfloat_sub96M(aPtr, bPtr, zPtr) softfloat_subM(3, aPtr, bPtr, zPtr) #endif #ifndef softfloat_sub128M @@ -1074,7 +954,7 @@ void | This function or macro is the same as 'softfloat_subM' with 'size_words' | = 4 (N = 128). *----------------------------------------------------------------------------*/ -#define softfloat_sub128M( aPtr, bPtr, zPtr ) softfloat_subM( 4, aPtr, bPtr, zPtr ) +#define softfloat_sub128M(aPtr, bPtr, zPtr) softfloat_subM(4, aPtr, bPtr, zPtr) #endif #ifndef softfloat_sub160M @@ -1082,7 +962,7 @@ void | This function or macro is the same as 'softfloat_subM' with 'size_words' | = 5 (N = 160). *----------------------------------------------------------------------------*/ -#define softfloat_sub160M( aPtr, bPtr, zPtr ) softfloat_subM( 5, aPtr, bPtr, zPtr ) +#define softfloat_sub160M(aPtr, bPtr, zPtr) softfloat_subM(5, aPtr, bPtr, zPtr) #endif #ifndef softfloat_mul64To128M @@ -1092,7 +972,7 @@ void | elements that concatenate in the platform's normal endian order to form a | 128-bit integer. *----------------------------------------------------------------------------*/ -void softfloat_mul64To128M( uint64_t a, uint64_t b, uint32_t *zPtr ); +void softfloat_mul64To128M(uint64_t a, uint64_t b, uint32_t* zPtr); #endif #ifndef softfloat_mul128MTo256M @@ -1104,9 +984,7 @@ void softfloat_mul64To128M( uint64_t a, uint64_t b, uint32_t *zPtr ); | Argument 'zPtr' points to an array of eight 32-bit elements that concatenate | to form a 256-bit integer. *----------------------------------------------------------------------------*/ -void - softfloat_mul128MTo256M( - const uint32_t *aPtr, const uint32_t *bPtr, uint32_t *zPtr ); +void softfloat_mul128MTo256M(const uint32_t* aPtr, const uint32_t* bPtr, uint32_t* zPtr); #endif #ifndef softfloat_remStepMBy32 @@ -1119,15 +997,8 @@ void | to a 'size_words'-long array of 32-bit elements that concatenate in the | platform's normal endian order to form an N-bit integer. *----------------------------------------------------------------------------*/ -void - softfloat_remStepMBy32( - uint_fast8_t size_words, - const uint32_t *remPtr, - uint_fast8_t dist, - const uint32_t *bPtr, - uint32_t q, - uint32_t *zPtr - ); +void softfloat_remStepMBy32(uint_fast8_t size_words, const uint32_t* remPtr, uint_fast8_t dist, const uint32_t* bPtr, uint32_t q, + uint32_t* zPtr); #endif #ifndef softfloat_remStep96MBy32 @@ -1135,7 +1006,7 @@ void | This function or macro is the same as 'softfloat_remStepMBy32' with | 'size_words' = 3 (N = 96). *----------------------------------------------------------------------------*/ -#define softfloat_remStep96MBy32( remPtr, dist, bPtr, q, zPtr ) softfloat_remStepMBy32( 3, remPtr, dist, bPtr, q, zPtr ) +#define softfloat_remStep96MBy32(remPtr, dist, bPtr, q, zPtr) softfloat_remStepMBy32(3, remPtr, dist, bPtr, q, zPtr) #endif #ifndef softfloat_remStep128MBy32 @@ -1143,7 +1014,7 @@ void | This function or macro is the same as 'softfloat_remStepMBy32' with | 'size_words' = 4 (N = 128). *----------------------------------------------------------------------------*/ -#define softfloat_remStep128MBy32( remPtr, dist, bPtr, q, zPtr ) softfloat_remStepMBy32( 4, remPtr, dist, bPtr, q, zPtr ) +#define softfloat_remStep128MBy32(remPtr, dist, bPtr, q, zPtr) softfloat_remStepMBy32(4, remPtr, dist, bPtr, q, zPtr) #endif #ifndef softfloat_remStep160MBy32 @@ -1151,10 +1022,9 @@ void | This function or macro is the same as 'softfloat_remStepMBy32' with | 'size_words' = 5 (N = 160). *----------------------------------------------------------------------------*/ -#define softfloat_remStep160MBy32( remPtr, dist, bPtr, q, zPtr ) softfloat_remStepMBy32( 5, remPtr, dist, bPtr, q, zPtr ) +#define softfloat_remStep160MBy32(remPtr, dist, bPtr, q, zPtr) softfloat_remStepMBy32(5, remPtr, dist, bPtr, q, zPtr) #endif #endif #endif - diff --git a/softfloat/source/include/softfloat.h b/softfloat/source/include/softfloat.h index b33374c..f07211e 100644 --- a/softfloat/source/include/softfloat.h +++ b/softfloat/source/include/softfloat.h @@ -34,7 +34,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ - /*============================================================================ | Note: If SoftFloat is made available as a general library for programs to | use, it is strongly recommended that a platform-specific version of this @@ -42,13 +41,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | eliminates all dependencies on compile-time macros. *============================================================================*/ - #ifndef softfloat_h #define softfloat_h 1 +#include "softfloat_types.h" #include #include -#include "softfloat_types.h" #ifndef THREAD_LOCAL #define THREAD_LOCAL @@ -58,10 +56,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | Software floating-point underflow tininess-detection mode. *----------------------------------------------------------------------------*/ extern THREAD_LOCAL uint_fast8_t softfloat_detectTininess; -enum { - softfloat_tininess_beforeRounding = 0, - softfloat_tininess_afterRounding = 1 -}; +enum { softfloat_tininess_beforeRounding = 0, softfloat_tininess_afterRounding = 1 }; /*---------------------------------------------------------------------------- | Software floating-point rounding mode. (Mode "odd" is supported only if @@ -69,12 +64,12 @@ enum { *----------------------------------------------------------------------------*/ extern THREAD_LOCAL uint_fast8_t softfloat_roundingMode; enum { - softfloat_round_near_even = 0, - softfloat_round_minMag = 1, - softfloat_round_min = 2, - softfloat_round_max = 3, + softfloat_round_near_even = 0, + softfloat_round_minMag = 1, + softfloat_round_min = 2, + softfloat_round_max = 3, softfloat_round_near_maxMag = 4, - softfloat_round_odd = 6 + softfloat_round_odd = 6 }; /*---------------------------------------------------------------------------- @@ -82,162 +77,162 @@ enum { *----------------------------------------------------------------------------*/ extern THREAD_LOCAL uint_fast8_t softfloat_exceptionFlags; enum { - softfloat_flag_inexact = 1, - softfloat_flag_underflow = 2, - softfloat_flag_overflow = 4, - softfloat_flag_infinite = 8, - softfloat_flag_invalid = 16 + softfloat_flag_inexact = 1, + softfloat_flag_underflow = 2, + softfloat_flag_overflow = 4, + softfloat_flag_infinite = 8, + softfloat_flag_invalid = 16 }; /*---------------------------------------------------------------------------- | Routine to raise any or all of the software floating-point exception flags. *----------------------------------------------------------------------------*/ -void softfloat_raiseFlags( uint_fast8_t ); +void softfloat_raiseFlags(uint_fast8_t); /*---------------------------------------------------------------------------- | Integer-to-floating-point conversion routines. *----------------------------------------------------------------------------*/ -float16_t ui32_to_f16( uint32_t ); -float32_t ui32_to_f32( uint32_t ); -float64_t ui32_to_f64( uint32_t ); +float16_t ui32_to_f16(uint32_t); +float32_t ui32_to_f32(uint32_t); +float64_t ui32_to_f64(uint32_t); #ifdef SOFTFLOAT_FAST_INT64 -extFloat80_t ui32_to_extF80( uint32_t ); -float128_t ui32_to_f128( uint32_t ); +extFloat80_t ui32_to_extF80(uint32_t); +float128_t ui32_to_f128(uint32_t); #endif -void ui32_to_extF80M( uint32_t, extFloat80_t * ); -void ui32_to_f128M( uint32_t, float128_t * ); -float16_t ui64_to_f16( uint64_t ); -float32_t ui64_to_f32( uint64_t ); -float64_t ui64_to_f64( uint64_t ); +void ui32_to_extF80M(uint32_t, extFloat80_t*); +void ui32_to_f128M(uint32_t, float128_t*); +float16_t ui64_to_f16(uint64_t); +float32_t ui64_to_f32(uint64_t); +float64_t ui64_to_f64(uint64_t); #ifdef SOFTFLOAT_FAST_INT64 -extFloat80_t ui64_to_extF80( uint64_t ); -float128_t ui64_to_f128( uint64_t ); +extFloat80_t ui64_to_extF80(uint64_t); +float128_t ui64_to_f128(uint64_t); #endif -void ui64_to_extF80M( uint64_t, extFloat80_t * ); -void ui64_to_f128M( uint64_t, float128_t * ); -float16_t i32_to_f16( int32_t ); -float32_t i32_to_f32( int32_t ); -float64_t i32_to_f64( int32_t ); +void ui64_to_extF80M(uint64_t, extFloat80_t*); +void ui64_to_f128M(uint64_t, float128_t*); +float16_t i32_to_f16(int32_t); +float32_t i32_to_f32(int32_t); +float64_t i32_to_f64(int32_t); #ifdef SOFTFLOAT_FAST_INT64 -extFloat80_t i32_to_extF80( int32_t ); -float128_t i32_to_f128( int32_t ); +extFloat80_t i32_to_extF80(int32_t); +float128_t i32_to_f128(int32_t); #endif -void i32_to_extF80M( int32_t, extFloat80_t * ); -void i32_to_f128M( int32_t, float128_t * ); -float16_t i64_to_f16( int64_t ); -float32_t i64_to_f32( int64_t ); -float64_t i64_to_f64( int64_t ); +void i32_to_extF80M(int32_t, extFloat80_t*); +void i32_to_f128M(int32_t, float128_t*); +float16_t i64_to_f16(int64_t); +float32_t i64_to_f32(int64_t); +float64_t i64_to_f64(int64_t); #ifdef SOFTFLOAT_FAST_INT64 -extFloat80_t i64_to_extF80( int64_t ); -float128_t i64_to_f128( int64_t ); +extFloat80_t i64_to_extF80(int64_t); +float128_t i64_to_f128(int64_t); #endif -void i64_to_extF80M( int64_t, extFloat80_t * ); -void i64_to_f128M( int64_t, float128_t * ); +void i64_to_extF80M(int64_t, extFloat80_t*); +void i64_to_f128M(int64_t, float128_t*); /*---------------------------------------------------------------------------- | 16-bit (half-precision) floating-point operations. *----------------------------------------------------------------------------*/ -uint_fast32_t f16_to_ui32( float16_t, uint_fast8_t, bool ); -uint_fast64_t f16_to_ui64( float16_t, uint_fast8_t, bool ); -int_fast32_t f16_to_i32( float16_t, uint_fast8_t, bool ); -int_fast64_t f16_to_i64( float16_t, uint_fast8_t, bool ); -uint_fast32_t f16_to_ui32_r_minMag( float16_t, bool ); -uint_fast64_t f16_to_ui64_r_minMag( float16_t, bool ); -int_fast32_t f16_to_i32_r_minMag( float16_t, bool ); -int_fast64_t f16_to_i64_r_minMag( float16_t, bool ); -float32_t f16_to_f32( float16_t ); -float64_t f16_to_f64( float16_t ); +uint_fast32_t f16_to_ui32(float16_t, uint_fast8_t, bool); +uint_fast64_t f16_to_ui64(float16_t, uint_fast8_t, bool); +int_fast32_t f16_to_i32(float16_t, uint_fast8_t, bool); +int_fast64_t f16_to_i64(float16_t, uint_fast8_t, bool); +uint_fast32_t f16_to_ui32_r_minMag(float16_t, bool); +uint_fast64_t f16_to_ui64_r_minMag(float16_t, bool); +int_fast32_t f16_to_i32_r_minMag(float16_t, bool); +int_fast64_t f16_to_i64_r_minMag(float16_t, bool); +float32_t f16_to_f32(float16_t); +float64_t f16_to_f64(float16_t); #ifdef SOFTFLOAT_FAST_INT64 -extFloat80_t f16_to_extF80( float16_t ); -float128_t f16_to_f128( float16_t ); +extFloat80_t f16_to_extF80(float16_t); +float128_t f16_to_f128(float16_t); #endif -void f16_to_extF80M( float16_t, extFloat80_t * ); -void f16_to_f128M( float16_t, float128_t * ); -float16_t f16_roundToInt( float16_t, uint_fast8_t, bool ); -float16_t f16_add( float16_t, float16_t ); -float16_t f16_sub( float16_t, float16_t ); -float16_t f16_mul( float16_t, float16_t ); -float16_t f16_mulAdd( float16_t, float16_t, float16_t ); -float16_t f16_div( float16_t, float16_t ); -float16_t f16_rem( float16_t, float16_t ); -float16_t f16_sqrt( float16_t ); -bool f16_eq( float16_t, float16_t ); -bool f16_le( float16_t, float16_t ); -bool f16_lt( float16_t, float16_t ); -bool f16_eq_signaling( float16_t, float16_t ); -bool f16_le_quiet( float16_t, float16_t ); -bool f16_lt_quiet( float16_t, float16_t ); -bool f16_isSignalingNaN( float16_t ); +void f16_to_extF80M(float16_t, extFloat80_t*); +void f16_to_f128M(float16_t, float128_t*); +float16_t f16_roundToInt(float16_t, uint_fast8_t, bool); +float16_t f16_add(float16_t, float16_t); +float16_t f16_sub(float16_t, float16_t); +float16_t f16_mul(float16_t, float16_t); +float16_t f16_mulAdd(float16_t, float16_t, float16_t); +float16_t f16_div(float16_t, float16_t); +float16_t f16_rem(float16_t, float16_t); +float16_t f16_sqrt(float16_t); +bool f16_eq(float16_t, float16_t); +bool f16_le(float16_t, float16_t); +bool f16_lt(float16_t, float16_t); +bool f16_eq_signaling(float16_t, float16_t); +bool f16_le_quiet(float16_t, float16_t); +bool f16_lt_quiet(float16_t, float16_t); +bool f16_isSignalingNaN(float16_t); /*---------------------------------------------------------------------------- | 32-bit (single-precision) floating-point operations. *----------------------------------------------------------------------------*/ -uint_fast32_t f32_to_ui32( float32_t, uint_fast8_t, bool ); -uint_fast64_t f32_to_ui64( float32_t, uint_fast8_t, bool ); -int_fast32_t f32_to_i32( float32_t, uint_fast8_t, bool ); -int_fast64_t f32_to_i64( float32_t, uint_fast8_t, bool ); -uint_fast32_t f32_to_ui32_r_minMag( float32_t, bool ); -uint_fast64_t f32_to_ui64_r_minMag( float32_t, bool ); -int_fast32_t f32_to_i32_r_minMag( float32_t, bool ); -int_fast64_t f32_to_i64_r_minMag( float32_t, bool ); -float16_t f32_to_f16( float32_t ); -float64_t f32_to_f64( float32_t ); +uint_fast32_t f32_to_ui32(float32_t, uint_fast8_t, bool); +uint_fast64_t f32_to_ui64(float32_t, uint_fast8_t, bool); +int_fast32_t f32_to_i32(float32_t, uint_fast8_t, bool); +int_fast64_t f32_to_i64(float32_t, uint_fast8_t, bool); +uint_fast32_t f32_to_ui32_r_minMag(float32_t, bool); +uint_fast64_t f32_to_ui64_r_minMag(float32_t, bool); +int_fast32_t f32_to_i32_r_minMag(float32_t, bool); +int_fast64_t f32_to_i64_r_minMag(float32_t, bool); +float16_t f32_to_f16(float32_t); +float64_t f32_to_f64(float32_t); #ifdef SOFTFLOAT_FAST_INT64 -extFloat80_t f32_to_extF80( float32_t ); -float128_t f32_to_f128( float32_t ); +extFloat80_t f32_to_extF80(float32_t); +float128_t f32_to_f128(float32_t); #endif -void f32_to_extF80M( float32_t, extFloat80_t * ); -void f32_to_f128M( float32_t, float128_t * ); -float32_t f32_roundToInt( float32_t, uint_fast8_t, bool ); -float32_t f32_add( float32_t, float32_t ); -float32_t f32_sub( float32_t, float32_t ); -float32_t f32_mul( float32_t, float32_t ); -float32_t f32_mulAdd( float32_t, float32_t, float32_t ); -float32_t f32_div( float32_t, float32_t ); -float32_t f32_rem( float32_t, float32_t ); -float32_t f32_sqrt( float32_t ); -bool f32_eq( float32_t, float32_t ); -bool f32_le( float32_t, float32_t ); -bool f32_lt( float32_t, float32_t ); -bool f32_eq_signaling( float32_t, float32_t ); -bool f32_le_quiet( float32_t, float32_t ); -bool f32_lt_quiet( float32_t, float32_t ); -bool f32_isSignalingNaN( float32_t ); +void f32_to_extF80M(float32_t, extFloat80_t*); +void f32_to_f128M(float32_t, float128_t*); +float32_t f32_roundToInt(float32_t, uint_fast8_t, bool); +float32_t f32_add(float32_t, float32_t); +float32_t f32_sub(float32_t, float32_t); +float32_t f32_mul(float32_t, float32_t); +float32_t f32_mulAdd(float32_t, float32_t, float32_t); +float32_t f32_div(float32_t, float32_t); +float32_t f32_rem(float32_t, float32_t); +float32_t f32_sqrt(float32_t); +bool f32_eq(float32_t, float32_t); +bool f32_le(float32_t, float32_t); +bool f32_lt(float32_t, float32_t); +bool f32_eq_signaling(float32_t, float32_t); +bool f32_le_quiet(float32_t, float32_t); +bool f32_lt_quiet(float32_t, float32_t); +bool f32_isSignalingNaN(float32_t); /*---------------------------------------------------------------------------- | 64-bit (double-precision) floating-point operations. *----------------------------------------------------------------------------*/ -uint_fast32_t f64_to_ui32( float64_t, uint_fast8_t, bool ); -uint_fast64_t f64_to_ui64( float64_t, uint_fast8_t, bool ); -int_fast32_t f64_to_i32( float64_t, uint_fast8_t, bool ); -int_fast64_t f64_to_i64( float64_t, uint_fast8_t, bool ); -uint_fast32_t f64_to_ui32_r_minMag( float64_t, bool ); -uint_fast64_t f64_to_ui64_r_minMag( float64_t, bool ); -int_fast32_t f64_to_i32_r_minMag( float64_t, bool ); -int_fast64_t f64_to_i64_r_minMag( float64_t, bool ); -float16_t f64_to_f16( float64_t ); -float32_t f64_to_f32( float64_t ); +uint_fast32_t f64_to_ui32(float64_t, uint_fast8_t, bool); +uint_fast64_t f64_to_ui64(float64_t, uint_fast8_t, bool); +int_fast32_t f64_to_i32(float64_t, uint_fast8_t, bool); +int_fast64_t f64_to_i64(float64_t, uint_fast8_t, bool); +uint_fast32_t f64_to_ui32_r_minMag(float64_t, bool); +uint_fast64_t f64_to_ui64_r_minMag(float64_t, bool); +int_fast32_t f64_to_i32_r_minMag(float64_t, bool); +int_fast64_t f64_to_i64_r_minMag(float64_t, bool); +float16_t f64_to_f16(float64_t); +float32_t f64_to_f32(float64_t); #ifdef SOFTFLOAT_FAST_INT64 -extFloat80_t f64_to_extF80( float64_t ); -float128_t f64_to_f128( float64_t ); +extFloat80_t f64_to_extF80(float64_t); +float128_t f64_to_f128(float64_t); #endif -void f64_to_extF80M( float64_t, extFloat80_t * ); -void f64_to_f128M( float64_t, float128_t * ); -float64_t f64_roundToInt( float64_t, uint_fast8_t, bool ); -float64_t f64_add( float64_t, float64_t ); -float64_t f64_sub( float64_t, float64_t ); -float64_t f64_mul( float64_t, float64_t ); -float64_t f64_mulAdd( float64_t, float64_t, float64_t ); -float64_t f64_div( float64_t, float64_t ); -float64_t f64_rem( float64_t, float64_t ); -float64_t f64_sqrt( float64_t ); -bool f64_eq( float64_t, float64_t ); -bool f64_le( float64_t, float64_t ); -bool f64_lt( float64_t, float64_t ); -bool f64_eq_signaling( float64_t, float64_t ); -bool f64_le_quiet( float64_t, float64_t ); -bool f64_lt_quiet( float64_t, float64_t ); -bool f64_isSignalingNaN( float64_t ); +void f64_to_extF80M(float64_t, extFloat80_t*); +void f64_to_f128M(float64_t, float128_t*); +float64_t f64_roundToInt(float64_t, uint_fast8_t, bool); +float64_t f64_add(float64_t, float64_t); +float64_t f64_sub(float64_t, float64_t); +float64_t f64_mul(float64_t, float64_t); +float64_t f64_mulAdd(float64_t, float64_t, float64_t); +float64_t f64_div(float64_t, float64_t); +float64_t f64_rem(float64_t, float64_t); +float64_t f64_sqrt(float64_t); +bool f64_eq(float64_t, float64_t); +bool f64_le(float64_t, float64_t); +bool f64_lt(float64_t, float64_t); +bool f64_eq_signaling(float64_t, float64_t); +bool f64_le_quiet(float64_t, float64_t); +bool f64_lt_quiet(float64_t, float64_t); +bool f64_isSignalingNaN(float64_t); /*---------------------------------------------------------------------------- | Rounding precision for 80-bit extended double-precision floating-point. @@ -249,124 +244,118 @@ extern THREAD_LOCAL uint_fast8_t extF80_roundingPrecision; | 80-bit extended double-precision floating-point operations. *----------------------------------------------------------------------------*/ #ifdef SOFTFLOAT_FAST_INT64 -uint_fast32_t extF80_to_ui32( extFloat80_t, uint_fast8_t, bool ); -uint_fast64_t extF80_to_ui64( extFloat80_t, uint_fast8_t, bool ); -int_fast32_t extF80_to_i32( extFloat80_t, uint_fast8_t, bool ); -int_fast64_t extF80_to_i64( extFloat80_t, uint_fast8_t, bool ); -uint_fast32_t extF80_to_ui32_r_minMag( extFloat80_t, bool ); -uint_fast64_t extF80_to_ui64_r_minMag( extFloat80_t, bool ); -int_fast32_t extF80_to_i32_r_minMag( extFloat80_t, bool ); -int_fast64_t extF80_to_i64_r_minMag( extFloat80_t, bool ); -float16_t extF80_to_f16( extFloat80_t ); -float32_t extF80_to_f32( extFloat80_t ); -float64_t extF80_to_f64( extFloat80_t ); -float128_t extF80_to_f128( extFloat80_t ); -extFloat80_t extF80_roundToInt( extFloat80_t, uint_fast8_t, bool ); -extFloat80_t extF80_add( extFloat80_t, extFloat80_t ); -extFloat80_t extF80_sub( extFloat80_t, extFloat80_t ); -extFloat80_t extF80_mul( extFloat80_t, extFloat80_t ); -extFloat80_t extF80_div( extFloat80_t, extFloat80_t ); -extFloat80_t extF80_rem( extFloat80_t, extFloat80_t ); -extFloat80_t extF80_sqrt( extFloat80_t ); -bool extF80_eq( extFloat80_t, extFloat80_t ); -bool extF80_le( extFloat80_t, extFloat80_t ); -bool extF80_lt( extFloat80_t, extFloat80_t ); -bool extF80_eq_signaling( extFloat80_t, extFloat80_t ); -bool extF80_le_quiet( extFloat80_t, extFloat80_t ); -bool extF80_lt_quiet( extFloat80_t, extFloat80_t ); -bool extF80_isSignalingNaN( extFloat80_t ); +uint_fast32_t extF80_to_ui32(extFloat80_t, uint_fast8_t, bool); +uint_fast64_t extF80_to_ui64(extFloat80_t, uint_fast8_t, bool); +int_fast32_t extF80_to_i32(extFloat80_t, uint_fast8_t, bool); +int_fast64_t extF80_to_i64(extFloat80_t, uint_fast8_t, bool); +uint_fast32_t extF80_to_ui32_r_minMag(extFloat80_t, bool); +uint_fast64_t extF80_to_ui64_r_minMag(extFloat80_t, bool); +int_fast32_t extF80_to_i32_r_minMag(extFloat80_t, bool); +int_fast64_t extF80_to_i64_r_minMag(extFloat80_t, bool); +float16_t extF80_to_f16(extFloat80_t); +float32_t extF80_to_f32(extFloat80_t); +float64_t extF80_to_f64(extFloat80_t); +float128_t extF80_to_f128(extFloat80_t); +extFloat80_t extF80_roundToInt(extFloat80_t, uint_fast8_t, bool); +extFloat80_t extF80_add(extFloat80_t, extFloat80_t); +extFloat80_t extF80_sub(extFloat80_t, extFloat80_t); +extFloat80_t extF80_mul(extFloat80_t, extFloat80_t); +extFloat80_t extF80_div(extFloat80_t, extFloat80_t); +extFloat80_t extF80_rem(extFloat80_t, extFloat80_t); +extFloat80_t extF80_sqrt(extFloat80_t); +bool extF80_eq(extFloat80_t, extFloat80_t); +bool extF80_le(extFloat80_t, extFloat80_t); +bool extF80_lt(extFloat80_t, extFloat80_t); +bool extF80_eq_signaling(extFloat80_t, extFloat80_t); +bool extF80_le_quiet(extFloat80_t, extFloat80_t); +bool extF80_lt_quiet(extFloat80_t, extFloat80_t); +bool extF80_isSignalingNaN(extFloat80_t); #endif -uint_fast32_t extF80M_to_ui32( const extFloat80_t *, uint_fast8_t, bool ); -uint_fast64_t extF80M_to_ui64( const extFloat80_t *, uint_fast8_t, bool ); -int_fast32_t extF80M_to_i32( const extFloat80_t *, uint_fast8_t, bool ); -int_fast64_t extF80M_to_i64( const extFloat80_t *, uint_fast8_t, bool ); -uint_fast32_t extF80M_to_ui32_r_minMag( const extFloat80_t *, bool ); -uint_fast64_t extF80M_to_ui64_r_minMag( const extFloat80_t *, bool ); -int_fast32_t extF80M_to_i32_r_minMag( const extFloat80_t *, bool ); -int_fast64_t extF80M_to_i64_r_minMag( const extFloat80_t *, bool ); -float16_t extF80M_to_f16( const extFloat80_t * ); -float32_t extF80M_to_f32( const extFloat80_t * ); -float64_t extF80M_to_f64( const extFloat80_t * ); -void extF80M_to_f128M( const extFloat80_t *, float128_t * ); -void - extF80M_roundToInt( - const extFloat80_t *, uint_fast8_t, bool, extFloat80_t * ); -void extF80M_add( const extFloat80_t *, const extFloat80_t *, extFloat80_t * ); -void extF80M_sub( const extFloat80_t *, const extFloat80_t *, extFloat80_t * ); -void extF80M_mul( const extFloat80_t *, const extFloat80_t *, extFloat80_t * ); -void extF80M_div( const extFloat80_t *, const extFloat80_t *, extFloat80_t * ); -void extF80M_rem( const extFloat80_t *, const extFloat80_t *, extFloat80_t * ); -void extF80M_sqrt( const extFloat80_t *, extFloat80_t * ); -bool extF80M_eq( const extFloat80_t *, const extFloat80_t * ); -bool extF80M_le( const extFloat80_t *, const extFloat80_t * ); -bool extF80M_lt( const extFloat80_t *, const extFloat80_t * ); -bool extF80M_eq_signaling( const extFloat80_t *, const extFloat80_t * ); -bool extF80M_le_quiet( const extFloat80_t *, const extFloat80_t * ); -bool extF80M_lt_quiet( const extFloat80_t *, const extFloat80_t * ); -bool extF80M_isSignalingNaN( const extFloat80_t * ); +uint_fast32_t extF80M_to_ui32(const extFloat80_t*, uint_fast8_t, bool); +uint_fast64_t extF80M_to_ui64(const extFloat80_t*, uint_fast8_t, bool); +int_fast32_t extF80M_to_i32(const extFloat80_t*, uint_fast8_t, bool); +int_fast64_t extF80M_to_i64(const extFloat80_t*, uint_fast8_t, bool); +uint_fast32_t extF80M_to_ui32_r_minMag(const extFloat80_t*, bool); +uint_fast64_t extF80M_to_ui64_r_minMag(const extFloat80_t*, bool); +int_fast32_t extF80M_to_i32_r_minMag(const extFloat80_t*, bool); +int_fast64_t extF80M_to_i64_r_minMag(const extFloat80_t*, bool); +float16_t extF80M_to_f16(const extFloat80_t*); +float32_t extF80M_to_f32(const extFloat80_t*); +float64_t extF80M_to_f64(const extFloat80_t*); +void extF80M_to_f128M(const extFloat80_t*, float128_t*); +void extF80M_roundToInt(const extFloat80_t*, uint_fast8_t, bool, extFloat80_t*); +void extF80M_add(const extFloat80_t*, const extFloat80_t*, extFloat80_t*); +void extF80M_sub(const extFloat80_t*, const extFloat80_t*, extFloat80_t*); +void extF80M_mul(const extFloat80_t*, const extFloat80_t*, extFloat80_t*); +void extF80M_div(const extFloat80_t*, const extFloat80_t*, extFloat80_t*); +void extF80M_rem(const extFloat80_t*, const extFloat80_t*, extFloat80_t*); +void extF80M_sqrt(const extFloat80_t*, extFloat80_t*); +bool extF80M_eq(const extFloat80_t*, const extFloat80_t*); +bool extF80M_le(const extFloat80_t*, const extFloat80_t*); +bool extF80M_lt(const extFloat80_t*, const extFloat80_t*); +bool extF80M_eq_signaling(const extFloat80_t*, const extFloat80_t*); +bool extF80M_le_quiet(const extFloat80_t*, const extFloat80_t*); +bool extF80M_lt_quiet(const extFloat80_t*, const extFloat80_t*); +bool extF80M_isSignalingNaN(const extFloat80_t*); /*---------------------------------------------------------------------------- | 128-bit (quadruple-precision) floating-point operations. *----------------------------------------------------------------------------*/ #ifdef SOFTFLOAT_FAST_INT64 -uint_fast32_t f128_to_ui32( float128_t, uint_fast8_t, bool ); -uint_fast64_t f128_to_ui64( float128_t, uint_fast8_t, bool ); -int_fast32_t f128_to_i32( float128_t, uint_fast8_t, bool ); -int_fast64_t f128_to_i64( float128_t, uint_fast8_t, bool ); -uint_fast32_t f128_to_ui32_r_minMag( float128_t, bool ); -uint_fast64_t f128_to_ui64_r_minMag( float128_t, bool ); -int_fast32_t f128_to_i32_r_minMag( float128_t, bool ); -int_fast64_t f128_to_i64_r_minMag( float128_t, bool ); -float16_t f128_to_f16( float128_t ); -float32_t f128_to_f32( float128_t ); -float64_t f128_to_f64( float128_t ); -extFloat80_t f128_to_extF80( float128_t ); -float128_t f128_roundToInt( float128_t, uint_fast8_t, bool ); -float128_t f128_add( float128_t, float128_t ); -float128_t f128_sub( float128_t, float128_t ); -float128_t f128_mul( float128_t, float128_t ); -float128_t f128_mulAdd( float128_t, float128_t, float128_t ); -float128_t f128_div( float128_t, float128_t ); -float128_t f128_rem( float128_t, float128_t ); -float128_t f128_sqrt( float128_t ); -bool f128_eq( float128_t, float128_t ); -bool f128_le( float128_t, float128_t ); -bool f128_lt( float128_t, float128_t ); -bool f128_eq_signaling( float128_t, float128_t ); -bool f128_le_quiet( float128_t, float128_t ); -bool f128_lt_quiet( float128_t, float128_t ); -bool f128_isSignalingNaN( float128_t ); +uint_fast32_t f128_to_ui32(float128_t, uint_fast8_t, bool); +uint_fast64_t f128_to_ui64(float128_t, uint_fast8_t, bool); +int_fast32_t f128_to_i32(float128_t, uint_fast8_t, bool); +int_fast64_t f128_to_i64(float128_t, uint_fast8_t, bool); +uint_fast32_t f128_to_ui32_r_minMag(float128_t, bool); +uint_fast64_t f128_to_ui64_r_minMag(float128_t, bool); +int_fast32_t f128_to_i32_r_minMag(float128_t, bool); +int_fast64_t f128_to_i64_r_minMag(float128_t, bool); +float16_t f128_to_f16(float128_t); +float32_t f128_to_f32(float128_t); +float64_t f128_to_f64(float128_t); +extFloat80_t f128_to_extF80(float128_t); +float128_t f128_roundToInt(float128_t, uint_fast8_t, bool); +float128_t f128_add(float128_t, float128_t); +float128_t f128_sub(float128_t, float128_t); +float128_t f128_mul(float128_t, float128_t); +float128_t f128_mulAdd(float128_t, float128_t, float128_t); +float128_t f128_div(float128_t, float128_t); +float128_t f128_rem(float128_t, float128_t); +float128_t f128_sqrt(float128_t); +bool f128_eq(float128_t, float128_t); +bool f128_le(float128_t, float128_t); +bool f128_lt(float128_t, float128_t); +bool f128_eq_signaling(float128_t, float128_t); +bool f128_le_quiet(float128_t, float128_t); +bool f128_lt_quiet(float128_t, float128_t); +bool f128_isSignalingNaN(float128_t); #endif -uint_fast32_t f128M_to_ui32( const float128_t *, uint_fast8_t, bool ); -uint_fast64_t f128M_to_ui64( const float128_t *, uint_fast8_t, bool ); -int_fast32_t f128M_to_i32( const float128_t *, uint_fast8_t, bool ); -int_fast64_t f128M_to_i64( const float128_t *, uint_fast8_t, bool ); -uint_fast32_t f128M_to_ui32_r_minMag( const float128_t *, bool ); -uint_fast64_t f128M_to_ui64_r_minMag( const float128_t *, bool ); -int_fast32_t f128M_to_i32_r_minMag( const float128_t *, bool ); -int_fast64_t f128M_to_i64_r_minMag( const float128_t *, bool ); -float16_t f128M_to_f16( const float128_t * ); -float32_t f128M_to_f32( const float128_t * ); -float64_t f128M_to_f64( const float128_t * ); -void f128M_to_extF80M( const float128_t *, extFloat80_t * ); -void f128M_roundToInt( const float128_t *, uint_fast8_t, bool, float128_t * ); -void f128M_add( const float128_t *, const float128_t *, float128_t * ); -void f128M_sub( const float128_t *, const float128_t *, float128_t * ); -void f128M_mul( const float128_t *, const float128_t *, float128_t * ); -void - f128M_mulAdd( - const float128_t *, const float128_t *, const float128_t *, float128_t * - ); -void f128M_div( const float128_t *, const float128_t *, float128_t * ); -void f128M_rem( const float128_t *, const float128_t *, float128_t * ); -void f128M_sqrt( const float128_t *, float128_t * ); -bool f128M_eq( const float128_t *, const float128_t * ); -bool f128M_le( const float128_t *, const float128_t * ); -bool f128M_lt( const float128_t *, const float128_t * ); -bool f128M_eq_signaling( const float128_t *, const float128_t * ); -bool f128M_le_quiet( const float128_t *, const float128_t * ); -bool f128M_lt_quiet( const float128_t *, const float128_t * ); -bool f128M_isSignalingNaN( const float128_t * ); +uint_fast32_t f128M_to_ui32(const float128_t*, uint_fast8_t, bool); +uint_fast64_t f128M_to_ui64(const float128_t*, uint_fast8_t, bool); +int_fast32_t f128M_to_i32(const float128_t*, uint_fast8_t, bool); +int_fast64_t f128M_to_i64(const float128_t*, uint_fast8_t, bool); +uint_fast32_t f128M_to_ui32_r_minMag(const float128_t*, bool); +uint_fast64_t f128M_to_ui64_r_minMag(const float128_t*, bool); +int_fast32_t f128M_to_i32_r_minMag(const float128_t*, bool); +int_fast64_t f128M_to_i64_r_minMag(const float128_t*, bool); +float16_t f128M_to_f16(const float128_t*); +float32_t f128M_to_f32(const float128_t*); +float64_t f128M_to_f64(const float128_t*); +void f128M_to_extF80M(const float128_t*, extFloat80_t*); +void f128M_roundToInt(const float128_t*, uint_fast8_t, bool, float128_t*); +void f128M_add(const float128_t*, const float128_t*, float128_t*); +void f128M_sub(const float128_t*, const float128_t*, float128_t*); +void f128M_mul(const float128_t*, const float128_t*, float128_t*); +void f128M_mulAdd(const float128_t*, const float128_t*, const float128_t*, float128_t*); +void f128M_div(const float128_t*, const float128_t*, float128_t*); +void f128M_rem(const float128_t*, const float128_t*, float128_t*); +void f128M_sqrt(const float128_t*, float128_t*); +bool f128M_eq(const float128_t*, const float128_t*); +bool f128M_le(const float128_t*, const float128_t*); +bool f128M_lt(const float128_t*, const float128_t*); +bool f128M_eq_signaling(const float128_t*, const float128_t*); +bool f128M_le_quiet(const float128_t*, const float128_t*); +bool f128M_lt_quiet(const float128_t*, const float128_t*); +bool f128M_isSignalingNaN(const float128_t*); #endif - diff --git a/softfloat/source/include/softfloat_types.h b/softfloat/source/include/softfloat_types.h index bc30e31..3fcc9d5 100644 --- a/softfloat/source/include/softfloat_types.h +++ b/softfloat/source/include/softfloat_types.h @@ -47,10 +47,18 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | the types below may, if desired, be defined as aliases for the native types | (typically 'float' and 'double', and possibly 'long double'). *----------------------------------------------------------------------------*/ -typedef struct { uint16_t v; } float16_t; -typedef struct { uint32_t v; } float32_t; -typedef struct { uint64_t v; } float64_t; -typedef struct { uint64_t v[2]; } float128_t; +typedef struct { + uint16_t v; +} float16_t; +typedef struct { + uint32_t v; +} float32_t; +typedef struct { + uint64_t v; +} float64_t; +typedef struct { + uint64_t v[2]; +} float128_t; /*---------------------------------------------------------------------------- | The format of an 80-bit extended floating-point number in memory. This @@ -58,9 +66,15 @@ typedef struct { uint64_t v[2]; } float128_t; | named 'signif'. *----------------------------------------------------------------------------*/ #ifdef LITTLEENDIAN -struct extFloat80M { uint64_t signif; uint16_t signExp; }; +struct extFloat80M { + uint64_t signif; + uint16_t signExp; +}; #else -struct extFloat80M { uint16_t signExp; uint64_t signif; }; +struct extFloat80M { + uint16_t signExp; + uint64_t signif; +}; #endif /*---------------------------------------------------------------------------- @@ -78,4 +92,3 @@ struct extFloat80M { uint16_t signExp; uint64_t signif; }; typedef struct extFloat80M extFloat80_t; #endif - diff --git a/src-gen/.gitignore b/src-gen/.gitignore new file mode 100644 index 0000000..454f93f --- /dev/null +++ b/src-gen/.gitignore @@ -0,0 +1,3 @@ +/iss +/vm +/sysc \ No newline at end of file diff --git a/incl/iss/arch/hwl.h b/src/iss/arch/hwl.h similarity index 65% rename from incl/iss/arch/hwl.h rename to src/iss/arch/hwl.h index 9e954ba..2da5f3a 100644 --- a/incl/iss/arch/hwl.h +++ b/src/iss/arch/hwl.h @@ -35,6 +35,7 @@ #ifndef _RISCV_HART_M_P_HWL_H #define _RISCV_HART_M_P_HWL_H +#include "riscv_hart_common.h" #include namespace iss { @@ -46,49 +47,71 @@ public: using this_class = hwl; using reg_t = typename BASE::reg_t; - hwl(); + hwl(feature_config cfg = feature_config{}); virtual ~hwl() = default; protected: - iss::status read_custom_csr_reg(unsigned addr, reg_t &val) override; + iss::status read_custom_csr_reg(unsigned addr, reg_t& val) override; iss::status write_custom_csr_reg(unsigned addr, reg_t val) override; }; - -template -inline hwl::hwl() { - for (unsigned addr = 0x800; addr < 0x803; ++addr){ +template +inline hwl::hwl(feature_config cfg) +: BASE(cfg) { + for(unsigned addr = 0x800; addr < 0x803; ++addr) { this->register_custom_csr_rd(addr); this->register_custom_csr_wr(addr); } - for (unsigned addr = 0x804; addr < 0x807; ++addr){ + for(unsigned addr = 0x804; addr < 0x807; ++addr) { this->register_custom_csr_rd(addr); this->register_custom_csr_wr(addr); } } -template -inline iss::status iss::arch::hwl::read_custom_csr_reg(unsigned addr, reg_t &val) { - switch(addr){ - case 0x800: val = this->reg.lpstart0; break; - case 0x801: val = this->reg.lpend0; break; - case 0x802: val = this->reg.lpcount0; break; - case 0x804: val = this->reg.lpstart1; break; - case 0x805: val = this->reg.lpend1; break; - case 0x806: val = this->reg.lpcount1; break; +template inline iss::status iss::arch::hwl::read_custom_csr_reg(unsigned addr, reg_t& val) { + switch(addr) { + case 0x800: + val = this->reg.lpstart0; + break; + case 0x801: + val = this->reg.lpend0; + break; + case 0x802: + val = this->reg.lpcount0; + break; + case 0x804: + val = this->reg.lpstart1; + break; + case 0x805: + val = this->reg.lpend1; + break; + case 0x806: + val = this->reg.lpcount1; + break; } return iss::Ok; } -template -inline iss::status iss::arch::hwl::write_custom_csr_reg(unsigned addr, reg_t val) { - switch(addr){ - case 0x800: this->reg.lpstart0 = val; break; - case 0x801: this->reg.lpend0 = val; break; - case 0x802: this->reg.lpcount0 = val; break; - case 0x804: this->reg.lpstart1 = val; break; - case 0x805: this->reg.lpend1 = val; break; - case 0x806: this->reg.lpcount1 = val; break; +template inline iss::status iss::arch::hwl::write_custom_csr_reg(unsigned addr, reg_t val) { + switch(addr) { + case 0x800: + this->reg.lpstart0 = val; + break; + case 0x801: + this->reg.lpend0 = val; + break; + case 0x802: + this->reg.lpcount0 = val; + break; + case 0x804: + this->reg.lpstart1 = val; + break; + case 0x805: + this->reg.lpend1 = val; + break; + case 0x806: + this->reg.lpcount1 = val; + break; } return iss::Ok; } @@ -96,5 +119,4 @@ inline iss::status iss::arch::hwl::write_custom_csr_reg(unsigned addr, reg } // namespace arch } // namespace iss - #endif /* _RISCV_HART_M_P_H */ diff --git a/incl/iss/arch/riscv_hart_common.h b/src/iss/arch/riscv_hart_common.h similarity index 82% rename from incl/iss/arch/riscv_hart_common.h rename to src/iss/arch/riscv_hart_common.h index 345fbeb..4ac086d 100644 --- a/incl/iss/arch/riscv_hart_common.h +++ b/src/iss/arch/riscv_hart_common.h @@ -43,7 +43,7 @@ namespace arch { enum { tohost_dflt = 0xF0001000, fromhost_dflt = 0xF0001040 }; -enum features_e{FEAT_NONE, FEAT_PMP=1, FEAT_EXT_N=2, FEAT_CLIC=4, FEAT_DEBUG=8, FEAT_TCM=16}; +enum features_e { FEAT_NONE, FEAT_PMP = 1, FEAT_EXT_N = 2, FEAT_CLIC = 4, FEAT_DEBUG = 8, FEAT_TCM = 16 }; enum riscv_csr { /* user-level CSR */ @@ -51,12 +51,18 @@ enum riscv_csr { ustatus = 0x000, uie = 0x004, utvec = 0x005, + utvt = 0x007, // CLIC // User Trap Handling uscratch = 0x040, uepc = 0x041, ucause = 0x042, utval = 0x043, uip = 0x044, + uxnti = 0x045, // CLIC + uintstatus = 0xCB1, // MRW Current interrupt levels (CLIC) - addr subject to change + uintthresh = 0x047, // MRW Interrupt-level threshold (CLIC) - addr subject to change + uscratchcsw = 0x048, // MRW Conditional scratch swap on priv mode change (CLIC) + uscratchcswl = 0x049, // MRW Conditional scratch swap on level change (CLIC) // User Floating-Point CSRs fflags = 0x001, frm = 0x002, @@ -106,19 +112,18 @@ enum riscv_csr { mie = 0x304, mtvec = 0x305, mcounteren = 0x306, - mtvt = 0x307, //CLIC + mtvt = 0x307, // CLIC // Machine Trap Handling mscratch = 0x340, mepc = 0x341, mcause = 0x342, mtval = 0x343, mip = 0x344, - mxnti = 0x345, //CLIC - mintstatus = 0x346, // MRW Current interrupt levels (CLIC) - addr subject to change - mscratchcsw = 0x348, // MRW Conditional scratch swap on priv mode change (CLIC) + mxnti = 0x345, // CLIC + mintstatus = 0xFB1, // MRW Current interrupt levels (CLIC) - addr subject to change + mintthresh = 0x347, // MRW Interrupt-level threshold (CLIC) - addr subject to change + mscratchcsw = 0x348, // MRW Conditional scratch swap on priv mode change (CLIC) mscratchcswl = 0x349, // MRW Conditional scratch swap on level change (CLIC) - mintthresh = 0x350, // MRW Interrupt-level threshold (CLIC) - addr subject to change - mclicbase = 0x351, // MRW Base address for CLIC memory mapped registers (CLIC) - addr subject to change // Physical Memory Protection pmpcfg0 = 0x3A0, pmpcfg1 = 0x3A1, @@ -170,7 +175,6 @@ enum riscv_csr { dscratch1 = 0x7B3 }; - enum { PGSHIFT = 12, PTE_PPN_SHIFT = 10, @@ -188,7 +192,7 @@ enum { template inline bool PTE_TABLE(T PTE) { return (((PTE) & (PTE_V | PTE_R | PTE_W | PTE_X)) == PTE_V); } -enum { PRIV_U = 0, PRIV_S = 1, PRIV_M = 3, PRIV_D = 4}; +enum { PRIV_U = 0, PRIV_S = 1, PRIV_M = 3, PRIV_D = 4 }; enum { ISA_A = 1, @@ -216,10 +220,13 @@ struct vm_info { struct feature_config { uint64_t clic_base{0xc0000000}; + unsigned clic_int_ctl_bits{4}; unsigned clic_num_irq{16}; unsigned clic_num_trigger{0}; uint64_t tcm_base{0x10000000}; uint64_t tcm_size{0x8000}; + uint64_t io_address{0xf0000000}; + uint64_t io_addr_mask{0xf0000000}; }; class trap_load_access_fault : public trap_access { @@ -248,49 +255,49 @@ public: : trap_access(15 << 16, badaddr) {} }; -inline void read_reg_uint32(uint64_t offs, uint32_t& reg, uint8_t *const data, unsigned length) { +inline void read_reg_uint32(uint64_t offs, uint32_t& reg, uint8_t* const data, unsigned length) { auto reg_ptr = reinterpret_cast(®); - switch (offs & 0x3) { + switch(offs & 0x3) { case 0: - for (auto i = 0U; i < length; ++i) + for(auto i = 0U; i < length; ++i) *(data + i) = *(reg_ptr + i); - break; + break; case 1: - for (auto i = 0U; i < length; ++i) + for(auto i = 0U; i < length; ++i) *(data + i) = *(reg_ptr + 1 + i); - break; + break; case 2: - for (auto i = 0U; i < length; ++i) + for(auto i = 0U; i < length; ++i) *(data + i) = *(reg_ptr + 2 + i); - break; + break; case 3: *data = *(reg_ptr + 3); - break; + break; } } -inline void write_reg_uint32(uint64_t offs, uint32_t& reg, const uint8_t *const data, unsigned length) { +inline void write_reg_uint32(uint64_t offs, uint32_t& reg, const uint8_t* const data, unsigned length) { auto reg_ptr = reinterpret_cast(®); - switch (offs & 0x3) { + switch(offs & 0x3) { case 0: - for (auto i = 0U; i < length; ++i) + for(auto i = 0U; i < length; ++i) *(reg_ptr + i) = *(data + i); - break; + break; case 1: - for (auto i = 0U; i < length; ++i) + for(auto i = 0U; i < length; ++i) *(reg_ptr + 1 + i) = *(data + i); - break; + break; case 2: - for (auto i = 0U; i < length; ++i) + for(auto i = 0U; i < length; ++i) *(reg_ptr + 2 + i) = *(data + i); - break; + break; case 3: - *(reg_ptr + 3) = *data ; - break; + *(reg_ptr + 3) = *data; + break; } } -} -} +} // namespace arch +} // namespace iss #endif diff --git a/src/iss/arch/riscv_hart_m_p.h b/src/iss/arch/riscv_hart_m_p.h new file mode 100644 index 0000000..e22c970 --- /dev/null +++ b/src/iss/arch/riscv_hart_m_p.h @@ -0,0 +1,1326 @@ +/******************************************************************************* + * Copyright (C) 2019 - 2023 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 implementation + ******************************************************************************/ + +#ifndef _RISCV_HART_M_P_H +#define _RISCV_HART_M_P_H + +#include "iss/arch/traits.h" +#include "iss/instrumentation_if.h" +#include "iss/log_categories.h" +#include "iss/vm_if.h" +#include "riscv_hart_common.h" +#ifndef FMT_HEADER_ONLY +#define FMT_HEADER_ONLY +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(__GNUC__) +#define likely(x) __builtin_expect(!!(x), 1) +#define unlikely(x) __builtin_expect(!!(x), 0) +#else +#define likely(x) x +#define unlikely(x) x +#endif + +namespace iss { +namespace arch { + +template class riscv_hart_m_p : public BASE { +protected: + const std::array lvl = {{'U', 'S', 'H', 'M'}}; + const std::array trap_str = {{"" + "Instruction address misaligned", // 0 + "Instruction access fault", // 1 + "Illegal instruction", // 2 + "Breakpoint", // 3 + "Load address misaligned", // 4 + "Load access fault", // 5 + "Store/AMO address misaligned", // 6 + "Store/AMO access fault", // 7 + "Environment call from U-mode", // 8 + "Environment call from S-mode", // 9 + "Reserved", // a + "Environment call from M-mode", // b + "Instruction page fault", // c + "Load page fault", // d + "Reserved", // e + "Store/AMO page fault"}}; + const std::array irq_str = {{"User software interrupt", "Supervisor software interrupt", "Reserved", + "Machine software interrupt", "User timer interrupt", "Supervisor timer interrupt", + "Reserved", "Machine timer interrupt", "User external interrupt", + "Supervisor external interrupt", "Reserved", "Machine external interrupt"}}; + +public: + using core = BASE; + using this_class = riscv_hart_m_p; + using phys_addr_t = typename core::phys_addr_t; + using reg_t = typename core::reg_t; + using addr_t = typename core::addr_t; + + using rd_csr_f = iss::status (this_class::*)(unsigned addr, reg_t&); + using wr_csr_f = iss::status (this_class::*)(unsigned addr, reg_t); + using mem_read_f = iss::status(phys_addr_t addr, unsigned, uint8_t* const); + using mem_write_f = iss::status(phys_addr_t addr, unsigned, uint8_t const* const); + + // primary template + template struct hart_state {}; + // specialization 32bit + template class hart_state::value>::type> { + public: + BEGIN_BF_DECL(mstatus_t, T); + // SD bit is read-only and is set when either the FS or XS bits encode a Dirty state (i.e., SD=((FS==11) OR + // XS==11))) + BF_FIELD(SD, 31, 1); + // Trap SRET + BF_FIELD(TSR, 22, 1); + // Timeout Wait + BF_FIELD(TW, 21, 1); + // Trap Virtual Memory + BF_FIELD(TVM, 20, 1); + // Make eXecutable Readable + BF_FIELD(MXR, 19, 1); + // permit Supervisor User Memory access + BF_FIELD(SUM, 18, 1); + // Modify PRiVilege + BF_FIELD(MPRV, 17, 1); + // status of additional user-mode extensions and associated state, All off/None dirty or clean, some on/None + // dirty, some clean/Some dirty + BF_FIELD(XS, 15, 2); + // floating-point unit status Off/Initial/Clean/Dirty + BF_FIELD(FS, 13, 2); + // machine previous privilege + BF_FIELD(MPP, 11, 2); + // supervisor previous privilege + BF_FIELD(SPP, 8, 1); + // previous machine interrupt-enable + BF_FIELD(MPIE, 7, 1); + // previous supervisor interrupt-enable + BF_FIELD(SPIE, 5, 1); + // previous user interrupt-enable + BF_FIELD(UPIE, 4, 1); + // machine interrupt-enable + BF_FIELD(MIE, 3, 1); + // supervisor interrupt-enable + BF_FIELD(SIE, 1, 1); + // user interrupt-enable + BF_FIELD(UIE, 0, 1); + END_BF_DECL(); + + mstatus_t mstatus; + + static const reg_t mstatus_reset_val = 0x1800; + + void write_mstatus(T val) { + auto mask = get_mask() & 0xff; // MPP is hardcode as 0x3 + auto new_val = (mstatus.backing.val & ~mask) | (val & mask); + mstatus = new_val; + } + + static constexpr uint32_t get_mask() { + // return 0x807ff988UL; // 0b1000 0000 0111 1111 1111 1000 1000 1000 // only machine mode is supported + // +-SD + // | +-TSR + // | |+-TW + // | ||+-TVM + // | |||+-MXR + // | ||||+-SUM + // | |||||+-MPRV + // | |||||| +-XS + // | |||||| | +-FS + // | |||||| | | +-MPP + // | |||||| | | | +-SPP + // | |||||| | | | |+-MPIE + // | ||||||/|/|/| || +-MIE + return 0b00000000000000000001100010001000; + } + }; + + // specialization 64bit + template class hart_state::value>::type> { + public: + BEGIN_BF_DECL(mstatus_t, T); + // SD bit is read-only and is set when either the FS or XS bits encode a Dirty state (i.e., SD=((FS==11) OR + // XS==11))) + BF_FIELD(SD, 63, 1); + // value of XLEN for S-mode + BF_FIELD(SXL, 34, 2); + // value of XLEN for U-mode + BF_FIELD(UXL, 32, 2); + // Trap SRET + BF_FIELD(TSR, 22, 1); + // Timeout Wait + BF_FIELD(TW, 21, 1); + // Trap Virtual Memory + BF_FIELD(TVM, 20, 1); + // Make eXecutable Readable + BF_FIELD(MXR, 19, 1); + // permit Supervisor User Memory access + BF_FIELD(SUM, 18, 1); + // Modify PRiVilege + BF_FIELD(MPRV, 17, 1); + // status of additional user-mode extensions and associated state, All off/None dirty or clean, some on/None + // dirty, some clean/Some dirty + BF_FIELD(XS, 15, 2); + // floating-point unit status Off/Initial/Clean/Dirty + BF_FIELD(FS, 13, 2); + // machine previous privilege + BF_FIELD(MPP, 11, 2); + // supervisor previous privilege + BF_FIELD(SPP, 8, 1); + // previous machine interrupt-enable + BF_FIELD(MPIE, 7, 1); + // previous supervisor interrupt-enable + BF_FIELD(SPIE, 5, 1); + // previous user interrupt-enable + BF_FIELD(UPIE, 4, 1); + // machine interrupt-enable + BF_FIELD(MIE, 3, 1); + // supervisor interrupt-enable + BF_FIELD(SIE, 1, 1); + // user interrupt-enable + BF_FIELD(UIE, 0, 1); + END_BF_DECL(); + + mstatus_t mstatus; + + static const reg_t mstatus_reset_val = 0x1800; + + void write_mstatus(T val) { + auto mask = get_mask() & 0xff; // MPP is hardcode as 0x3 + auto new_val = (mstatus.backing.val & ~mask) | (val & mask); + mstatus = new_val; + } + + static constexpr T get_mask() { + // return 0x8000000f007ff9ddULL; // 0b1...0 1111 0000 0000 0111 1111 1111 1001 1011 1011 + // + // +-TSR + // |+-TW + // ||+-TVM + // |||+-MXR + // ||||+-SUM + // |||||+-MPRV + // |||||| +-XS + // |||||| | +-FS + // |||||| | | +-MPP + // |||||| | | | +-SPP + // |||||| | | | |+-MPIE + // ||||||/|/|/| || +-MIE + return 0b00000000000000000001100010001000; + } + }; + + using hart_state_type = hart_state; + + constexpr reg_t get_irq_mask() { + return 0b100010001000; // only machine mode is supported + } + + constexpr bool has_compressed() { return traits::MISA_VAL & 0b0100; } + constexpr reg_t get_pc_mask() { return has_compressed() ? (reg_t)~1 : (reg_t)~3; } + + riscv_hart_m_p(feature_config cfg = feature_config{}); + virtual ~riscv_hart_m_p() = default; + + void reset(uint64_t address) override; + + std::pair load_file(std::string name, int type = -1) override; + + iss::status read(const address_type type, const access_type access, const uint32_t space, const uint64_t addr, const unsigned length, + uint8_t* const data) override; + iss::status write(const address_type type, const access_type access, const uint32_t space, const uint64_t addr, const unsigned length, + const uint8_t* const data) override; + + uint64_t enter_trap(uint64_t flags) override { return riscv_hart_m_p::enter_trap(flags, fault_data, fault_data); } + uint64_t enter_trap(uint64_t flags, uint64_t addr, uint64_t instr) override; + uint64_t leave_trap(uint64_t flags) override; + + const reg_t& get_mhartid() const { return mhartid_reg; } + void set_mhartid(reg_t mhartid) { mhartid_reg = mhartid; }; + + void disass_output(uint64_t pc, const std::string instr) override { + CLOG(INFO, disass) << fmt::format("0x{:016x} {:40} [s:0x{:x};c:{}]", pc, instr, (reg_t)state.mstatus, + this->reg.icount + cycle_offset); + }; + + iss::instrumentation_if* get_instrumentation_if() override { return &instr_if; } + + void set_csr(unsigned addr, reg_t val) { csr[addr & csr.page_addr_mask] = val; } + + void set_irq_num(unsigned i) { mcause_max_irq = 1 << util::ilog2(i); } + +protected: + struct riscv_instrumentation_if : public iss::instrumentation_if { + + riscv_instrumentation_if(riscv_hart_m_p& arch) + : arch(arch) {} + /** + * get the name of this architecture + * + * @return the name of this architecture + */ + const std::string core_type_name() const override { return traits::core_type; } + + uint64_t get_pc() override { return arch.reg.PC; } + + uint64_t get_next_pc() override { return arch.reg.NEXT_PC; } + + uint64_t get_instr_word() override { return arch.reg.instruction; } + + uint64_t get_instr_count() override { return arch.reg.icount; } + + uint64_t get_pendig_traps() override { return arch.reg.trap_state; } + + uint64_t get_total_cycles() override { return arch.reg.icount + arch.cycle_offset; } + + void update_last_instr_cycles(unsigned cycles) override { arch.cycle_offset += cycles - 1; } + + bool is_branch_taken() override { return arch.reg.last_branch; } + + unsigned get_reg_num() override { return traits::NUM_REGS; } + + unsigned get_reg_size(unsigned num) override { return traits::reg_bit_widths[num]; } + + riscv_hart_m_p& arch; + }; + + friend struct riscv_instrumentation_if; + + virtual iss::status read_mem(phys_addr_t addr, unsigned length, uint8_t* const data); + virtual iss::status write_mem(phys_addr_t addr, unsigned length, const uint8_t* const data); + + iss::status read_clic(uint64_t addr, unsigned length, uint8_t* const data); + iss::status write_clic(uint64_t addr, unsigned length, const uint8_t* const data); + + virtual iss::status read_csr(unsigned addr, reg_t& val); + virtual iss::status write_csr(unsigned addr, reg_t val); + + hart_state_type state; + int64_t cycle_offset{0}; + uint64_t mcycle_csr{0}; + int64_t instret_offset{0}; + uint64_t minstret_csr{0}; + reg_t fault_data; + uint64_t tohost = tohost_dflt; + uint64_t fromhost = fromhost_dflt; + unsigned to_host_wr_cnt = 0; + riscv_instrumentation_if instr_if; + + using mem_type = util::sparse_array; + using csr_type = util::sparse_array::reg_t, 1ULL << 12, 12>; + using csr_page_type = typename csr_type::page_type; + mem_type mem; + csr_type csr; + std::stringstream uart_buf; + std::unordered_map ptw; + std::unordered_map atomic_reservation; + std::unordered_map csr_rd_cb; + std::unordered_map csr_wr_cb; + uint8_t clic_cfg_reg{0}; + std::array clic_inttrig_reg; + union clic_int_reg_t { + struct { + uint8_t ip; + uint8_t ie; + uint8_t attr; + uint8_t ctl; + }; + uint32_t raw; + }; + std::vector clic_int_reg; + uint8_t clic_mprev_lvl{0}; + uint8_t clic_mact_lvl{0}; + + std::vector tcm; + + iss::status read_csr_reg(unsigned addr, reg_t& val); + iss::status write_csr_reg(unsigned addr, reg_t val); + iss::status read_null(unsigned addr, reg_t& val); + iss::status write_null(unsigned addr, reg_t val) { return iss::status::Ok; } + iss::status read_cycle(unsigned addr, reg_t& val); + iss::status write_cycle(unsigned addr, reg_t val); + iss::status read_instret(unsigned addr, reg_t& val); + iss::status write_instret(unsigned addr, reg_t val); + iss::status read_tvec(unsigned addr, reg_t& val); + iss::status read_time(unsigned addr, reg_t& val); + iss::status read_status(unsigned addr, reg_t& val); + iss::status write_status(unsigned addr, reg_t val); + iss::status read_cause(unsigned addr, reg_t& val); + iss::status write_cause(unsigned addr, reg_t val); + iss::status read_ie(unsigned addr, reg_t& val); + iss::status write_ie(unsigned addr, reg_t val); + iss::status read_ip(unsigned addr, reg_t& val); + iss::status read_hartid(unsigned addr, reg_t& val); + iss::status write_epc(unsigned addr, reg_t val); + iss::status read_intstatus(unsigned addr, reg_t& val); + iss::status write_intthresh(unsigned addr, reg_t val); + iss::status write_xtvt(unsigned addr, reg_t val); + iss::status write_dcsr_dcsr(unsigned addr, reg_t val); + iss::status read_dcsr_reg(unsigned addr, reg_t& val); + iss::status write_dcsr_reg(unsigned addr, reg_t val); + iss::status read_dpc_reg(unsigned addr, reg_t& val); + iss::status write_dpc_reg(unsigned addr, reg_t val); + + virtual iss::status read_custom_csr_reg(unsigned addr, reg_t& val) { return iss::status::Err; }; + virtual iss::status write_custom_csr_reg(unsigned addr, reg_t val) { return iss::status::Err; }; + + void register_custom_csr_rd(unsigned addr) { csr_rd_cb[addr] = &this_class::read_custom_csr_reg; } + void register_custom_csr_wr(unsigned addr) { csr_wr_cb[addr] = &this_class::write_custom_csr_reg; } + + reg_t mhartid_reg{0x0}; + + void check_interrupt(); + bool pmp_check(const access_type type, const uint64_t addr, const unsigned len); + std::vector> memfn_range; + std::vector> memfn_read; + std::vector> memfn_write; + void insert_mem_range(uint64_t, uint64_t, std::function, std::function); + feature_config cfg; + unsigned mcause_max_irq{(FEAT & features_e::FEAT_CLIC) ? std::max(16U, static_cast(traits::CLIC_NUM_IRQ)) : 16U}; + inline bool debug_mode_active() { return this->reg.PRIV & 0x4; } + std::pair, std::function> replace_mem_access(std::function rd, + std::function wr) { + std::pair, std::function> ret{hart_mem_rd_delegate, hart_mem_wr_delegate}; + hart_mem_rd_delegate = rd; + hart_mem_wr_delegate = wr; + return ret; + } + std::function hart_mem_rd_delegate; + std::function hart_mem_wr_delegate; +}; + +template +riscv_hart_m_p::riscv_hart_m_p(feature_config cfg) +: state() +, instr_if(*this) +, cfg(cfg) { + // reset values + csr[misa] = traits::MISA_VAL; + csr[mvendorid] = 0x669; + csr[marchid] = traits::MARCHID_VAL; + csr[mimpid] = 1; + + uart_buf.str(""); + for(unsigned addr = mhpmcounter3; addr <= mhpmcounter31; ++addr) { + csr_rd_cb[addr] = &this_class::read_null; + csr_wr_cb[addr] = &this_class::write_csr_reg; + } + if(traits::XLEN == 32) + for(unsigned addr = mhpmcounter3h; addr <= mhpmcounter31h; ++addr) { + csr_rd_cb[addr] = &this_class::read_null; + csr_wr_cb[addr] = &this_class::write_csr_reg; + } + for(unsigned addr = mhpmevent3; addr <= mhpmevent31; ++addr) { + csr_rd_cb[addr] = &this_class::read_null; + csr_wr_cb[addr] = &this_class::write_csr_reg; + } + for(unsigned addr = hpmcounter3; addr <= hpmcounter31; ++addr) { + csr_rd_cb[addr] = &this_class::read_null; + } + if(traits::XLEN == 32) + for(unsigned addr = hpmcounter3h; addr <= hpmcounter31h; ++addr) { + csr_rd_cb[addr] = &this_class::read_null; + // csr_wr_cb[addr] = &this_class::write_csr_reg; + } + // common regs + const std::array roaddrs{{misa, mvendorid, marchid, mimpid}}; + for(auto addr : roaddrs) { + csr_rd_cb[addr] = &this_class::read_csr_reg; + csr_wr_cb[addr] = &this_class::write_null; + } + const std::array rwaddrs{{mepc, mtvec, mscratch, mtval}}; + for(auto addr : rwaddrs) { + csr_rd_cb[addr] = &this_class::read_csr_reg; + csr_wr_cb[addr] = &this_class::write_csr_reg; + } + // special handling & overrides + csr_rd_cb[time] = &this_class::read_time; + if(traits::XLEN == 32) + csr_rd_cb[timeh] = &this_class::read_time; + csr_rd_cb[cycle] = &this_class::read_cycle; + if(traits::XLEN == 32) + csr_rd_cb[cycleh] = &this_class::read_cycle; + csr_rd_cb[instret] = &this_class::read_instret; + if(traits::XLEN == 32) + csr_rd_cb[instreth] = &this_class::read_instret; + + csr_rd_cb[mcycle] = &this_class::read_cycle; + csr_wr_cb[mcycle] = &this_class::write_cycle; + if(traits::XLEN == 32) + csr_rd_cb[mcycleh] = &this_class::read_cycle; + if(traits::XLEN == 32) + csr_wr_cb[mcycleh] = &this_class::write_cycle; + csr_rd_cb[minstret] = &this_class::read_instret; + csr_wr_cb[minstret] = &this_class::write_instret; + if(traits::XLEN == 32) + csr_rd_cb[minstreth] = &this_class::read_instret; + if(traits::XLEN == 32) + csr_wr_cb[minstreth] = &this_class::write_instret; + csr_rd_cb[mstatus] = &this_class::read_status; + csr_wr_cb[mstatus] = &this_class::write_status; + csr_rd_cb[mcause] = &this_class::read_cause; + csr_wr_cb[mcause] = &this_class::write_cause; + csr_rd_cb[mtvec] = &this_class::read_tvec; + csr_wr_cb[mepc] = &this_class::write_epc; + csr_rd_cb[mip] = &this_class::read_ip; + csr_wr_cb[mip] = &this_class::write_null; + csr_rd_cb[mie] = &this_class::read_ie; + csr_wr_cb[mie] = &this_class::write_ie; + csr_rd_cb[mhartid] = &this_class::read_hartid; + csr_wr_cb[misa] = &this_class::write_null; + csr_wr_cb[mvendorid] = &this_class::write_null; + csr_wr_cb[marchid] = &this_class::write_null; + csr_wr_cb[mimpid] = &this_class::write_null; + if(FEAT & FEAT_CLIC) { + csr_rd_cb[mtvt] = &this_class::read_csr_reg; + csr_wr_cb[mtvt] = &this_class::write_xtvt; + // csr_rd_cb[mxnti] = &this_class::read_csr_reg; + // csr_wr_cb[mxnti] = &this_class::write_csr_reg; + csr_rd_cb[mintstatus] = &this_class::read_intstatus; + csr_wr_cb[mintstatus] = &this_class::write_null; + // csr_rd_cb[mscratchcsw] = &this_class::read_csr_reg; + // csr_wr_cb[mscratchcsw] = &this_class::write_csr_reg; + // csr_rd_cb[mscratchcswl] = &this_class::read_csr_reg; + // csr_wr_cb[mscratchcswl] = &this_class::write_csr_reg; + csr_rd_cb[mintthresh] = &this_class::read_csr_reg; + csr_wr_cb[mintthresh] = &this_class::write_intthresh; + clic_int_reg.resize(cfg.clic_num_irq, clic_int_reg_t{.raw = 0}); + clic_cfg_reg = 0x20; + clic_mact_lvl = clic_mprev_lvl = (1 << (cfg.clic_int_ctl_bits)) - 1; + csr[mintthresh] = (1 << (cfg.clic_int_ctl_bits)) - 1; + insert_mem_range( + cfg.clic_base, 0x5000UL, + [this](phys_addr_t addr, unsigned length, uint8_t* const data) { return read_clic(addr.val, length, data); }, + [this](phys_addr_t addr, unsigned length, uint8_t const* const data) { return write_clic(addr.val, length, data); }); + } + if(FEAT & FEAT_TCM) { + tcm.resize(cfg.tcm_size); + std::function read_clic_cb = [this](phys_addr_t addr, unsigned length, uint8_t* const data) { + auto offset = addr.val - this->cfg.tcm_base; + std::copy(tcm.data() + offset, tcm.data() + offset + length, data); + return iss::Ok; + }; + std::function write_clic_cb = [this](phys_addr_t addr, unsigned length, uint8_t const* const data) { + auto offset = addr.val - this->cfg.tcm_base; + std::copy(data, data + length, tcm.data() + offset); + return iss::Ok; + }; + insert_mem_range(cfg.tcm_base, cfg.tcm_size, read_clic_cb, write_clic_cb); + } + if(FEAT & FEAT_DEBUG) { + csr_wr_cb[dscratch0] = &this_class::write_dcsr_reg; + csr_rd_cb[dscratch0] = &this_class::read_dcsr_reg; + csr_wr_cb[dscratch1] = &this_class::write_dcsr_reg; + csr_rd_cb[dscratch1] = &this_class::read_dcsr_reg; + csr_wr_cb[dpc] = &this_class::write_dpc_reg; + csr_rd_cb[dpc] = &this_class::read_dpc_reg; + csr_wr_cb[dcsr] = &this_class::write_dcsr_dcsr; + csr_rd_cb[dcsr] = &this_class::read_dcsr_reg; + } + hart_mem_rd_delegate = [this](phys_addr_t a, unsigned l, uint8_t* const d) -> iss::status { return this->read_mem(a, l, d); }; + hart_mem_wr_delegate = [this](phys_addr_t a, unsigned l, uint8_t const* const d) -> iss::status { return this->write_mem(a, l, d); }; +} + +template std::pair riscv_hart_m_p::load_file(std::string name, int type) { + FILE* fp = fopen(name.c_str(), "r"); + if(fp) { + std::array buf; + auto n = fread(buf.data(), 1, 4, fp); + fclose(fp); + if(n != 4) + throw std::runtime_error("input file has insufficient size"); + buf[4] = 0; + if(strcmp(buf.data() + 1, "ELF") == 0) { + // Create elfio reader + ELFIO::elfio reader; + // Load ELF data + if(!reader.load(name)) + throw std::runtime_error("could not process elf file"); + // check elf properties + if(reader.get_class() != ELFCLASS32) + if(sizeof(reg_t) == 4) + throw std::runtime_error("wrong elf class in file"); + if(reader.get_type() != ET_EXEC) + throw std::runtime_error("wrong elf type in file"); + if(reader.get_machine() != EM_RISCV) + throw std::runtime_error("wrong elf machine in file"); + auto entry = reader.get_entry(); + for(const auto pseg : reader.segments) { + const auto fsize = pseg->get_file_size(); // 0x42c/0x0 + const auto seg_data = pseg->get_data(); + if(fsize > 0) { + auto res = this->write(iss::address_type::PHYSICAL, iss::access_type::DEBUG_WRITE, traits::MEM, + pseg->get_physical_address(), fsize, reinterpret_cast(seg_data)); + if(res != iss::Ok) + LOG(ERR) << "problem writing " << fsize << "bytes to 0x" << std::hex << pseg->get_physical_address(); + } + } + for(const auto sec : reader.sections) { + if(sec->get_name() == ".symtab") { + if(SHT_SYMTAB == sec->get_type() || SHT_DYNSYM == sec->get_type()) { + ELFIO::symbol_section_accessor symbols(reader, sec); + auto sym_no = symbols.get_symbols_num(); + std::string name; + ELFIO::Elf64_Addr value = 0; + ELFIO::Elf_Xword size = 0; + unsigned char bind = 0; + unsigned char type = 0; + ELFIO::Elf_Half section = 0; + unsigned char other = 0; + for(auto i = 0U; i < sym_no; ++i) { + symbols.get_symbol(i, name, value, size, bind, type, section, other); + if(name == "tohost") { + tohost = value; + } else if(name == "fromhost") { + fromhost = value; + } + } + } + } else if(sec->get_name() == ".tohost") { + tohost = sec->get_address(); + fromhost = tohost + 0x40; + } + } + return std::make_pair(entry, true); + } + throw std::runtime_error(fmt::format("memory load file {} is not a valid elf file", name)); + } + throw std::runtime_error(fmt::format("memory load file not found, check if {} is a valid file", name)); +} + +template +inline void riscv_hart_m_p::insert_mem_range(uint64_t base, uint64_t size, std::function rd_f, + std::function wr_fn) { + std::tuple entry{base, size}; + auto it = std::upper_bound( + memfn_range.begin(), memfn_range.end(), entry, + [](std::tuple const& a, std::tuple const& b) { return std::get<0>(a) < std::get<0>(b); }); + auto idx = std::distance(memfn_range.begin(), it); + memfn_range.insert(it, entry); + memfn_read.insert(std::begin(memfn_read) + idx, rd_f); + memfn_write.insert(std::begin(memfn_write) + idx, wr_fn); +} + +template +iss::status riscv_hart_m_p::read(const address_type type, const access_type access, const uint32_t space, const uint64_t addr, + const unsigned length, uint8_t* const data) { +#ifndef NDEBUG + if(access && iss::access_type::DEBUG) { + LOG(TRACEALL) << "debug read of " << length << " bytes @addr 0x" << std::hex << addr; + } else if(access && iss::access_type::FETCH) { + LOG(TRACEALL) << "fetch of " << length << " bytes @addr 0x" << std::hex << addr; + } else { + LOG(TRACE) << "read of " << length << " bytes @addr 0x" << std::hex << addr; + } +#endif + try { + switch(space) { + case traits::MEM: { + auto alignment = is_fetch(access) ? (has_compressed() ? 2 : 4) : length; + if(unlikely(is_fetch(access) && (addr & (alignment - 1)))) { + fault_data = addr; + if(is_debug(access)) + throw trap_access(0, addr); + this->reg.trap_state = (1UL << 31); // issue trap 0 + return iss::Err; + } + try { + if(!is_debug(access) && (addr & (alignment - 1))) { + this->reg.trap_state = (1UL << 31) | 4 << 16; + fault_data = addr; + return iss::Err; + } + phys_addr_t phys_addr{access, space, addr}; + auto res = iss::Err; + if(access != access_type::FETCH && memfn_range.size()) { + auto it = + std::find_if(std::begin(memfn_range), std::end(memfn_range), [phys_addr](std::tuple const& a) { + return std::get<0>(a) <= phys_addr.val && (std::get<0>(a) + std::get<1>(a)) > phys_addr.val; + }); + if(it != std::end(memfn_range)) { + auto idx = std::distance(std::begin(memfn_range), it); + res = memfn_read[idx](phys_addr, length, data); + } else + res = hart_mem_rd_delegate(phys_addr, length, data); + } else { + res = hart_mem_rd_delegate(phys_addr, length, data); + } + if(unlikely(res != iss::Ok && (access & access_type::DEBUG) == 0)) { + this->reg.trap_state = (1UL << 31) | (5 << 16); // issue trap 5 (load access fault + fault_data = addr; + } + return res; + } catch(trap_access& ta) { + this->reg.trap_state = (1UL << 31) | ta.id; + fault_data = ta.addr; + return iss::Err; + } + } break; + case traits::CSR: { + if(length != sizeof(reg_t)) + return iss::Err; + return read_csr(addr, *reinterpret_cast(data)); + } break; + case traits::FENCE: { + if((addr + length) > mem.size()) + return iss::Err; + return iss::Ok; + } break; + case traits::RES: { + auto it = atomic_reservation.find(addr); + if(it != atomic_reservation.end() && it->second != 0) { + memset(data, 0xff, length); + atomic_reservation.erase(addr); + } else + memset(data, 0, length); + } break; + default: + return iss::Err; // assert("Not supported"); + } + return iss::Ok; + } catch(trap_access& ta) { + this->reg.trap_state = (1UL << 31) | ta.id; + fault_data = ta.addr; + return iss::Err; + } +} + +template +iss::status riscv_hart_m_p::write(const address_type type, const access_type access, const uint32_t space, const uint64_t addr, + const unsigned length, const uint8_t* const data) { +#ifndef NDEBUG + const char* prefix = (access && iss::access_type::DEBUG) ? "debug " : ""; + switch(length) { + case 8: + LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint64_t*)&data[0] << std::dec << ") @addr 0x" + << std::hex << addr; + break; + case 4: + LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint32_t*)&data[0] << std::dec << ") @addr 0x" + << std::hex << addr; + break; + case 2: + LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint16_t*)&data[0] << std::dec << ") @addr 0x" + << std::hex << addr; + break; + case 1: + LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << (uint16_t)data[0] << std::dec << ") @addr 0x" + << std::hex << addr; + break; + default: + LOG(TRACE) << prefix << "write of " << length << " bytes @addr " << addr; + } +#endif + try { + switch(space) { + case traits::MEM: { + if(unlikely((access && iss::access_type::FETCH) && (addr & 0x1) == 1)) { + fault_data = addr; + if(access && iss::access_type::DEBUG) + throw trap_access(0, addr); + this->reg.trap_state = (1UL << 31); // issue trap 0 + return iss::Err; + } + try { + if(length > 1 && (addr & (length - 1)) && (access & access_type::DEBUG) != access_type::DEBUG) { + this->reg.trap_state = (1UL << 31) | 6 << 16; + fault_data = addr; + return iss::Err; + } + phys_addr_t phys_addr{access, space, addr}; + auto res = iss::Err; + if(access != access_type::FETCH && memfn_range.size()) { + auto it = + std::find_if(std::begin(memfn_range), std::end(memfn_range), [phys_addr](std::tuple const& a) { + return std::get<0>(a) <= phys_addr.val && (std::get<0>(a) + std::get<1>(a)) > phys_addr.val; + }); + if(it != std::end(memfn_range)) { + auto idx = std::distance(std::begin(memfn_range), it); + res = memfn_write[idx](phys_addr, length, data); + } else + res = write_mem(phys_addr, length, data); + } else { + res = write_mem(phys_addr, length, data); + } + if(unlikely(res != iss::Ok && (access & access_type::DEBUG) == 0)) { + this->reg.trap_state = (1UL << 31) | (7 << 16); // issue trap 7 (Store/AMO access fault) + fault_data = addr; + } + return res; + } catch(trap_access& ta) { + this->reg.trap_state = (1UL << 31) | ta.id; + fault_data = ta.addr; + return iss::Err; + } + + if((addr + length) > mem.size()) + return iss::Err; + switch(addr) { + case 0x10013000: // UART0 base, TXFIFO reg + case 0x10023000: // UART1 base, TXFIFO reg + uart_buf << (char)data[0]; + if(((char)data[0]) == '\n' || data[0] == 0) { + // LOG(INFO)<<"UART"<<((paddr.val>>16)&0x3)<<" send + // '"<::CSR: { + if(length != sizeof(reg_t)) + return iss::Err; + return write_csr(addr, *reinterpret_cast(data)); + } break; + case traits::FENCE: { + if((addr + length) > mem.size()) + return iss::Err; + switch(addr) { + case 2: + case 3: { + ptw.clear(); + auto tvm = state.mstatus.TVM; + return iss::Ok; + } + } + } break; + case traits::RES: { + atomic_reservation[addr] = data[0]; + } break; + default: + return iss::Err; + } + return iss::Ok; + } catch(trap_access& ta) { + this->reg.trap_state = (1UL << 31) | ta.id; + fault_data = ta.addr; + return iss::Err; + } +} + +template iss::status riscv_hart_m_p::read_csr(unsigned addr, reg_t& val) { + if(addr >= csr.size()) + return iss::Err; + auto req_priv_lvl = (addr >> 8) & 0x3; + if(this->reg.PRIV < req_priv_lvl) // not having required privileges + throw illegal_instruction_fault(this->fault_data); + auto it = csr_rd_cb.find(addr); + if(it == csr_rd_cb.end() || !it->second) // non existent register + throw illegal_instruction_fault(this->fault_data); + return (this->*(it->second))(addr, val); +} + +template iss::status riscv_hart_m_p::write_csr(unsigned addr, reg_t val) { + if(addr >= csr.size()) + return iss::Err; + auto req_priv_lvl = (addr >> 8) & 0x3; + if(this->reg.PRIV < req_priv_lvl) // not having required privileges + throw illegal_instruction_fault(this->fault_data); + if((addr & 0xc00) == 0xc00) // writing to read-only region + throw illegal_instruction_fault(this->fault_data); + auto it = csr_wr_cb.find(addr); + if(it == csr_wr_cb.end() || !it->second) // non existent register + throw illegal_instruction_fault(this->fault_data); + return (this->*(it->second))(addr, val); +} + +template iss::status riscv_hart_m_p::read_csr_reg(unsigned addr, reg_t& val) { + val = csr[addr]; + return iss::Ok; +} + +template iss::status riscv_hart_m_p::read_null(unsigned addr, reg_t& val) { + val = 0; + return iss::Ok; +} + +template iss::status riscv_hart_m_p::write_csr_reg(unsigned addr, reg_t val) { + csr[addr] = val; + return iss::Ok; +} + +template iss::status riscv_hart_m_p::read_cycle(unsigned addr, reg_t& val) { + auto cycle_val = this->reg.icount + cycle_offset; + if(addr == mcycle) { + val = static_cast(cycle_val); + } else if(addr == mcycleh) { + val = static_cast(cycle_val >> 32); + } + return iss::Ok; +} + +template iss::status riscv_hart_m_p::write_cycle(unsigned addr, reg_t val) { + if(sizeof(typename traits::reg_t) != 4) { + mcycle_csr = static_cast(val); + } else { + if(addr == mcycle) { + mcycle_csr = (mcycle_csr & 0xffffffff00000000) + val; + } else { + mcycle_csr = (static_cast(val) << 32) + (mcycle_csr & 0xffffffff); + } + } + cycle_offset = mcycle_csr - this->reg.icount; // TODO: relying on wrap-around + return iss::Ok; +} + +template iss::status riscv_hart_m_p::read_instret(unsigned addr, reg_t& val) { + if((addr & 0xff) == (minstret & 0xff)) { + val = static_cast(this->reg.instret); + } else if((addr & 0xff) == (minstreth & 0xff)) { + val = static_cast(this->reg.instret >> 32); + } + return iss::Ok; +} + +template iss::status riscv_hart_m_p::write_instret(unsigned addr, reg_t val) { + if(sizeof(typename traits::reg_t) != 4) { + this->reg.instret = static_cast(val); + } else { + if((addr & 0xff) == (minstret & 0xff)) { + this->reg.instret = (this->reg.instret & 0xffffffff00000000) + val; + } else { + this->reg.instret = (static_cast(val) << 32) + (this->reg.instret & 0xffffffff); + } + } + this->reg.instret--; + return iss::Ok; +} + +template iss::status riscv_hart_m_p::read_time(unsigned addr, reg_t& val) { + uint64_t time_val = this->reg.icount / (100000000 / 32768 - 1); //-> ~3052; + if(addr == time) { + val = static_cast(time_val); + } else if(addr == timeh) { + if(sizeof(typename traits::reg_t) != 4) + return iss::Err; + val = static_cast(time_val >> 32); + } + return iss::Ok; +} + +template iss::status riscv_hart_m_p::read_tvec(unsigned addr, reg_t& val) { + val = FEAT & features_e::FEAT_CLIC ? csr[addr] : csr[addr] & ~2; + return iss::Ok; +} + +template iss::status riscv_hart_m_p::read_status(unsigned addr, reg_t& val) { + val = state.mstatus & hart_state_type::get_mask(); + return iss::Ok; +} + +template iss::status riscv_hart_m_p::write_status(unsigned addr, reg_t val) { + state.write_mstatus(val); + check_interrupt(); + return iss::Ok; +} + +template iss::status riscv_hart_m_p::read_cause(unsigned addr, reg_t& val) { + if((FEAT & features_e::FEAT_CLIC) && (csr[mtvec] & 0x3) == 3) { + val = csr[addr] & ((1UL << (traits::XLEN - 1)) | (mcause_max_irq - 1) | (0xfUL << 16)); + val |= clic_mprev_lvl << 16; + val |= state.mstatus.MPIE << 27; + val |= state.mstatus.MPP << 28; + } else + val = csr[addr] & ((1UL << (traits::XLEN - 1)) | (mcause_max_irq - 1)); + return iss::Ok; +} + +template iss::status riscv_hart_m_p::write_cause(unsigned addr, reg_t val) { + if((FEAT & features_e::FEAT_CLIC) && (csr[mtvec] & 0x3) == 3) { + auto mask = ((1UL << (traits::XLEN - 1)) | (mcause_max_irq - 1) | (0xfUL << 16)); + csr[addr] = (val & mask) | (csr[addr] & ~mask); + clic_mprev_lvl = ((val >> 16) & 0xff) | (1 << (8 - cfg.clic_int_ctl_bits)) - 1; + state.mstatus.MPIE = (val >> 27) & 0x1; + state.mstatus.MPP = (val >> 28) & 0x3; + } else { + auto mask = ((1UL << (traits::XLEN - 1)) | (mcause_max_irq - 1)); + csr[addr] = (val & mask) | (csr[addr] & ~mask); + } + return iss::Ok; +} + +template iss::status riscv_hart_m_p::read_hartid(unsigned addr, reg_t& val) { + val = mhartid_reg; + return iss::Ok; +} + +template iss::status riscv_hart_m_p::read_ie(unsigned addr, reg_t& val) { + auto mask = get_irq_mask(); + val = csr[mie] & mask; + return iss::Ok; +} + +template iss::status riscv_hart_m_p::write_ie(unsigned addr, reg_t val) { + auto mask = get_irq_mask(); + csr[mie] = (csr[mie] & ~mask) | (val & mask); + check_interrupt(); + return iss::Ok; +} + +template iss::status riscv_hart_m_p::read_ip(unsigned addr, reg_t& val) { + auto mask = get_irq_mask(); + val = csr[mip] & mask; + return iss::Ok; +} + +template iss::status riscv_hart_m_p::write_epc(unsigned addr, reg_t val) { + csr[addr] = val & get_pc_mask(); + return iss::Ok; +} + +template iss::status riscv_hart_m_p::write_dcsr_dcsr(unsigned addr, reg_t val) { + if(!debug_mode_active()) + throw illegal_instruction_fault(this->fault_data); + // +-------------- ebreakm + // | +---------- stepi + // | | +++----- cause + // | | ||| +- step + csr[addr] = val & 0b1000100111000100U; + return iss::Ok; +} + +template iss::status riscv_hart_m_p::read_dcsr_reg(unsigned addr, reg_t& val) { + if(!debug_mode_active()) + throw illegal_instruction_fault(this->fault_data); + val = csr[addr]; + return iss::Ok; +} + +template iss::status riscv_hart_m_p::write_dcsr_reg(unsigned addr, reg_t val) { + if(!debug_mode_active()) + throw illegal_instruction_fault(this->fault_data); + csr[addr] = val; + return iss::Ok; +} + +template iss::status riscv_hart_m_p::read_dpc_reg(unsigned addr, reg_t& val) { + if(!debug_mode_active()) + throw illegal_instruction_fault(this->fault_data); + val = this->reg.DPC; + return iss::Ok; +} + +template iss::status riscv_hart_m_p::write_dpc_reg(unsigned addr, reg_t val) { + if(!debug_mode_active()) + throw illegal_instruction_fault(this->fault_data); + this->reg.DPC = val; + return iss::Ok; +} + +template iss::status riscv_hart_m_p::read_intstatus(unsigned addr, reg_t& val) { + val = (clic_mact_lvl & 0xff) << 24; + return iss::Ok; +} + +template iss::status riscv_hart_m_p::write_intthresh(unsigned addr, reg_t val) { + csr[addr] = (val & 0xff) | (1 << (cfg.clic_int_ctl_bits)) - 1; + return iss::Ok; +} + +template iss::status riscv_hart_m_p::write_xtvt(unsigned addr, reg_t val) { + csr[addr] = val & ~0x3fULL; + return iss::Ok; +} + +template +iss::status riscv_hart_m_p::read_mem(phys_addr_t paddr, unsigned length, uint8_t* const data) { + switch(paddr.val) { + default: { + for(auto offs = 0U; offs < length; ++offs) { + *(data + offs) = mem[(paddr.val + offs) % mem.size()]; + } + } + } + return iss::Ok; +} + +template +iss::status riscv_hart_m_p::write_mem(phys_addr_t paddr, unsigned length, const uint8_t* const data) { + switch(paddr.val) { + case 0xFFFF0000: // UART0 base, TXFIFO reg + if(((char)data[0]) == '\n' || data[0] == 0) { + LOG(INFO) << "UART" << ((paddr.val >> 12) & 0x3) << " send '" << uart_buf.str() << "'"; + uart_buf.str(""); + } else if(((char)data[0]) != '\r') + uart_buf << (char)data[0]; + break; + default: { + mem_type::page_type& p = mem(paddr.val / mem.page_size); + std::copy(data, data + length, p.data() + (paddr.val & mem.page_addr_mask)); + // tohost handling in case of riscv-test + if(paddr.access && iss::access_type::FUNC) { + auto tohost_upper = + (traits::XLEN == 32 && paddr.val == (tohost + 4)) || (traits::XLEN == 64 && paddr.val == tohost); + auto tohost_lower = (traits::XLEN == 32 && paddr.val == tohost) || (traits::XLEN == 64 && paddr.val == tohost); + if(tohost_lower || tohost_upper) { + uint64_t hostvar = *reinterpret_cast(p.data() + (tohost & mem.page_addr_mask)); + if(tohost_upper || (tohost_lower && to_host_wr_cnt > 0)) { + switch(hostvar >> 48) { + case 0: + if(hostvar != 0x1) { + LOG(FATAL) << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar + << "), stopping simulation"; + } else { + LOG(INFO) << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar + << "), stopping simulation"; + } + this->reg.trap_state = std::numeric_limits::max(); + this->interrupt_sim = hostvar; +#ifndef WITH_TCC + throw(iss::simulation_stopped(hostvar)); +#endif + break; + case 0x0101: { + char c = static_cast(hostvar & 0xff); + if(c == '\n' || c == 0) { + LOG(INFO) << "tohost send '" << uart_buf.str() << "'"; + uart_buf.str(""); + } else + uart_buf << c; + to_host_wr_cnt = 0; + } break; + default: + break; + } + } else if(tohost_lower) + to_host_wr_cnt++; + } else if((traits::XLEN == 32 && paddr.val == fromhost + 4) || (traits::XLEN == 64 && paddr.val == fromhost)) { + uint64_t fhostvar = *reinterpret_cast(p.data() + (fromhost & mem.page_addr_mask)); + *reinterpret_cast(p.data() + (tohost & mem.page_addr_mask)) = fhostvar; + } + } + } + } + return iss::Ok; +} + +template +iss::status riscv_hart_m_p::read_clic(uint64_t addr, unsigned length, uint8_t* const data) { + if(addr == cfg.clic_base) { // cliccfg + *data = clic_cfg_reg; + for(auto i = 1; i < length; ++i) + *(data + i) = 0; + } else if(addr >= (cfg.clic_base + 0x40) && (addr + length) <= (cfg.clic_base + 0x40 + cfg.clic_num_trigger * 4)) { // clicinttrig + auto offset = ((addr & 0x7fff) - 0x40) / 4; + read_reg_uint32(addr, clic_inttrig_reg[offset], data, length); + } else if(addr >= (cfg.clic_base + 0x1000) && + (addr + length) <= (cfg.clic_base + 0x1000 + cfg.clic_num_irq * 4)) { // clicintip/clicintie/clicintattr/clicintctl + auto offset = ((addr & 0x7fff) - 0x1000) / 4; + read_reg_uint32(addr, clic_int_reg[offset].raw, data, length); + } else { + for(auto i = 0U; i < length; ++i) + *(data + i) = 0; + } + return iss::Ok; +} + +template +iss::status riscv_hart_m_p::write_clic(uint64_t addr, unsigned length, const uint8_t* const data) { + if(addr == cfg.clic_base) { // cliccfg + clic_cfg_reg = (clic_cfg_reg & ~0x1e) | (*data & 0x1e); + } else if(addr >= (cfg.clic_base + 0x40) && (addr + length) <= (cfg.clic_base + 0x40 + cfg.clic_num_trigger * 4)) { // clicinttrig + auto offset = ((addr & 0x7fff) - 0x40) / 4; + write_reg_uint32(addr, clic_inttrig_reg[offset], data, length); + } else if(addr >= (cfg.clic_base + 0x1000) && + (addr + length) <= (cfg.clic_base + 0x1000 + cfg.clic_num_irq * 4)) { // clicintip/clicintie/clicintattr/clicintctl + auto offset = ((addr & 0x7fff) - 0x1000) / 4; + write_reg_uint32(addr, clic_int_reg[offset].raw, data, length); + clic_int_reg[offset].raw &= 0xf0c70101; // clicIntCtlBits->0xf0, clicintattr->0xc7, clicintie->0x1, clicintip->0x1 + } + return iss::Ok; +} + +template inline void riscv_hart_m_p::reset(uint64_t address) { + BASE::reset(address); + state.mstatus = hart_state_type::mstatus_reset_val; +} + +template void riscv_hart_m_p::check_interrupt() { + // TODO: Implement CLIC functionality + // auto ideleg = csr[mideleg]; + // Multiple simultaneous interrupts and traps at the same privilege level are + // handled in the following decreasing priority order: + // external interrupts, software interrupts, timer interrupts, then finally + // any synchronous traps. + auto ena_irq = csr[mip] & csr[mie]; + + bool mstatus_mie = state.mstatus.MIE; + auto m_enabled = this->reg.PRIV < PRIV_M || mstatus_mie; + auto enabled_interrupts = m_enabled ? ena_irq : 0; + + if(enabled_interrupts != 0) { + int res = 0; + while((enabled_interrupts & 1) == 0) { + enabled_interrupts >>= 1; + res++; + } + this->reg.pending_trap = res << 16 | 1; // 0x80 << 24 | (cause << 16) | trap_id + } +} + +template uint64_t riscv_hart_m_p::enter_trap(uint64_t flags, uint64_t addr, uint64_t instr) { + // flags are ACTIVE[31:31], CAUSE[30:16], TRAPID[15:0] + // calculate and write mcause val + auto const trap_id = bit_sub<0, 16>(flags); + auto cause = bit_sub<16, 15>(flags); + // calculate effective privilege level + unsigned new_priv = PRIV_M; + if(trap_id == 0) { // exception + if(cause == 11) + cause = 0x8 + PRIV_M; // adjust environment call cause + // store ret addr in xepc register + csr[mepc] = static_cast(addr) & get_pc_mask(); // store actual address instruction of exception + /* + * write mtval if new_priv=M_MODE, spec says: + * When a hardware breakpoint is triggered, or an instruction-fetch, load, + * or store address-misaligned, + * access, or page-fault exception occurs, mtval is written with the + * faulting effective address. + */ + switch(cause) { + case 0: + csr[mtval] = static_cast(addr); + break; + case 2: + csr[mtval] = (!has_compressed() || (instr & 0x3) == 3) ? instr : instr & 0xffff; + break; + case 3: + if((FEAT & FEAT_DEBUG) && (csr[dcsr] & 0x8000)) { + this->reg.DPC = addr; + csr[dcsr] = (csr[dcsr] & ~0x1c3) | (1 << 6) | PRIV_M; // FIXME: cause should not be 4 (stepi) + new_priv = this->reg.PRIV | PRIV_D; + } else { + csr[mtval] = addr; + } + break; + case 4: + case 6: + csr[mtval] = fault_data; + break; + default: + csr[mtval] = 0; + } + fault_data = 0; + } else { + csr[mepc] = this->reg.NEXT_PC & get_pc_mask(); // store next address if interrupt + this->reg.pending_trap = 0; + } + csr[mcause] = (trap_id << (traits::XLEN - 1)) + cause; + // update mstatus + // xPP field of mstatus is written with the active privilege mode at the time + // of the trap; the x PIE field of mstatus + // is written with the value of the active interrupt-enable bit at the time of + // the trap; and the x IE field of mstatus + // is cleared + // store the actual privilege level in yPP and store interrupt enable flags + state.mstatus.MPP = PRIV_M; + state.mstatus.MPIE = state.mstatus.MIE; + state.mstatus.MIE = false; + + // get trap vector + auto xtvec = csr[mtvec]; + // calculate adds// set NEXT_PC to trap addressess to jump to based on MODE + if((FEAT & features_e::FEAT_CLIC) && trap_id != 0 && (xtvec & 0x3UL) == 3UL) { + reg_t data; + auto ret = read(address_type::LOGICAL, access_type::READ, 0, csr[mtvt], sizeof(reg_t), reinterpret_cast(&data)); + if(ret == iss::Err) + return this->reg.PC; + this->reg.NEXT_PC = data; + } else { + // bits in mtvec + this->reg.NEXT_PC = xtvec & ~0x3UL; + if((xtvec & 0x1) == 1 && trap_id != 0) + this->reg.NEXT_PC += 4 * cause; + } + // reset trap state + this->reg.PRIV = new_priv; + this->reg.trap_state = 0; + std::array buffer; +#if defined(_MSC_VER) + sprintf(buffer.data(), "0x%016llx", addr); +#else + sprintf(buffer.data(), "0x%016lx", addr); +#endif + if((flags & 0xffffffff) != 0xffffffff) + CLOG(INFO, disass) << (trap_id ? "Interrupt" : "Trap") << " with cause '" << (trap_id ? irq_str[cause] : trap_str[cause]) << "' (" + << cause << ")" + << " at address " << buffer.data() << " occurred"; + return this->reg.NEXT_PC; +} + +template uint64_t riscv_hart_m_p::leave_trap(uint64_t flags) { + state.mstatus.MIE = state.mstatus.MPIE; + state.mstatus.MPIE = 1; + // sets the pc to the value stored in the x epc register. + this->reg.NEXT_PC = csr[mepc] & get_pc_mask(); + CLOG(INFO, disass) << "Executing xRET"; + check_interrupt(); + this->reg.trap_state = this->reg.pending_trap; + return this->reg.NEXT_PC; +} + +} // namespace arch +} // namespace iss + +#endif /* _RISCV_HART_M_P_H */ diff --git a/incl/iss/arch/riscv_hart_msu_vp.h b/src/iss/arch/riscv_hart_msu_vp.h similarity index 60% rename from incl/iss/arch/riscv_hart_msu_vp.h rename to src/iss/arch/riscv_hart_msu_vp.h index 607c952..2a4bc90 100644 --- a/incl/iss/arch/riscv_hart_msu_vp.h +++ b/src/iss/arch/riscv_hart_msu_vp.h @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (C) 2017, 2018, 2021 MINRES Technologies GmbH + * Copyright (C) 2017 - 2023 MINRES Technologies GmbH * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -35,22 +35,22 @@ #ifndef _RISCV_HART_MSU_VP_H #define _RISCV_HART_MSU_VP_H -#include "riscv_hart_common.h" #include "iss/arch/traits.h" #include "iss/instrumentation_if.h" #include "iss/log_categories.h" #include "iss/vm_if.h" +#include "riscv_hart_common.h" #ifndef FMT_HEADER_ONLY #define FMT_HEADER_ONLY #endif #include #include #include +#include #include #include #include #include -#include #include #include #include @@ -69,27 +69,28 @@ namespace arch { template class riscv_hart_msu_vp : public BASE { protected: const std::array lvl = {{'U', 'S', 'H', 'M'}}; - const std::array trap_str = {{"" - "Instruction address misaligned", // 0 - "Instruction access fault", // 1 - "Illegal instruction", // 2 - "Breakpoint", // 3 - "Load address misaligned", // 4 - "Load access fault", // 5 - "Store/AMO address misaligned", // 6 - "Store/AMO access fault", // 7 - "Environment call from U-mode", // 8 - "Environment call from S-mode", // 9 - "Reserved", // a - "Environment call from M-mode", // b - "Instruction page fault", // c - "Load page fault", // d - "Reserved", // e - "Store/AMO page fault"}}; - const std::array irq_str = { - {"User software interrupt", "Supervisor software interrupt", "Reserved", "Machine software interrupt", - "User timer interrupt", "Supervisor timer interrupt", "Reserved", "Machine timer interrupt", - "User external interrupt", "Supervisor external interrupt", "Reserved", "Machine external interrupt"}}; + const std::array trap_str = {{"" + "Instruction address misaligned", // 0 + "Instruction access fault", // 1 + "Illegal instruction", // 2 + "Breakpoint", // 3 + "Load address misaligned", // 4 + "Load access fault", // 5 + "Store/AMO address misaligned", // 6 + "Store/AMO access fault", // 7 + "Environment call from U-mode", // 8 + "Environment call from S-mode", // 9 + "Reserved", // a + "Environment call from M-mode", // b + "Instruction page fault", // c + "Load page fault", // d + "Reserved", // e + "Store/AMO page fault"}}; + const std::array irq_str = {{"User software interrupt", "Supervisor software interrupt", "Reserved", + "Machine software interrupt", "User timer interrupt", "Supervisor timer interrupt", + "Reserved", "Machine timer interrupt", "User external interrupt", + "Supervisor external interrupt", "Reserved", "Machine external interrupt"}}; + public: using core = BASE; using this_class = riscv_hart_msu_vp; @@ -98,7 +99,7 @@ public: using reg_t = typename core::reg_t; using addr_t = typename core::addr_t; - using rd_csr_f = iss::status (this_class::*)(unsigned addr, reg_t &); + using rd_csr_f = iss::status (this_class::*)(unsigned addr, reg_t&); using wr_csr_f = iss::status (this_class::*)(unsigned addr, reg_t); // primary template @@ -107,7 +108,8 @@ public: template class hart_state::value>::type> { public: BEGIN_BF_DECL(mstatus_t, T); - // SD bit is read-only and is set when either the FS or XS bits encode a Dirty state (i.e., SD=((FS==11) OR XS==11))) + // SD bit is read-only and is set when either the FS or XS bits encode a Dirty state (i.e., SD=((FS==11) OR + // XS==11))) BF_FIELD(SD, 31, 1); // Trap SRET BF_FIELD(TSR, 22, 1); @@ -121,7 +123,8 @@ public: BF_FIELD(SUM, 18, 1); // Modify PRiVilege BF_FIELD(MPRV, 17, 1); - // status of additional user-mode extensions and associated state, All off/None dirty or clean, some on/None dirty, some clean/Some dirty + // status of additional user-mode extensions and associated state, All off/None dirty or clean, some on/None + // dirty, some clean/Some dirty BF_FIELD(XS, 15, 2); // floating-point unit status Off/Initial/Clean/Dirty BF_FIELD(FS, 13, 2); @@ -161,21 +164,28 @@ public: #if __cplusplus < 201402L return priv_lvl == PRIV_U ? 0x80000011UL : priv_lvl == PRIV_S ? 0x800de133UL : 0x807ff9ddUL; #else - switch (priv_lvl) { - case PRIV_U: return 0x80000011UL; // 0b1000 0000 0000 0000 0000 0000 0001 0001 - case PRIV_S: return 0x800de133UL; // 0b1000 0000 0000 1101 1110 0001 0011 0011 - default: return 0x807ff9ddUL; // 0b1000 0000 0111 1111 1111 1001 1011 1011 + switch(priv_lvl) { + case PRIV_U: + return 0x80000011UL; // 0b1000 0000 0000 0000 0000 0000 0001 0001 + case PRIV_S: + return 0x800de133UL; // 0b1000 0000 0000 1101 1110 0001 0011 0011 + default: + return 0x807ff9ddUL; // 0b1000 0000 0111 1111 1111 1001 1011 1011 } #endif } static inline vm_info decode_vm_info(uint32_t state, T sptbr) { - if (state == PRIV_M) return {0, 0, 0, 0}; - if (state <= PRIV_S) - switch (bit_sub<31, 1>(sptbr)) { - case 0: return {0, 0, 0, 0}; // off - case 1: return {2, 10, 4, bit_sub<0, 22>(sptbr) << PGSHIFT}; // SV32 - default: abort(); + if(state == PRIV_M) + return {0, 0, 0, 0}; + if(state <= PRIV_S) + switch(bit_sub<31, 1>(sptbr)) { + case 0: + return {0, 0, 0, 0}; // off + case 1: + return {2, 10, 4, bit_sub<0, 22>(sptbr) << PGSHIFT}; // SV32 + default: + abort(); } abort(); return {0, 0, 0, 0}; // dummy @@ -185,7 +195,8 @@ public: template class hart_state::value>::type> { public: BEGIN_BF_DECL(mstatus_t, T); - // SD bit is read-only and is set when either the FS or XS bits encode a Dirty state (i.e., SD=((FS==11) OR XS==11))) + // SD bit is read-only and is set when either the FS or XS bits encode a Dirty state (i.e., SD=((FS==11) OR + // XS==11))) BF_FIELD(SD, 63, 1); // value of XLEN for S-mode BF_FIELD(SXL, 34, 2); @@ -203,7 +214,8 @@ public: BF_FIELD(SUM, 18, 1); // Modify PRiVilege BF_FIELD(MPRV, 17, 1); - // status of additional user-mode extensions and associated state, All off/None dirty or clean, some on/None dirty, some clean/Some dirty + // status of additional user-mode extensions and associated state, All off/None dirty or clean, some on/None + // dirty, some clean/Some dirty BF_FIELD(XS, 15, 2); // floating-point unit status Off/Initial/Clean/Dirty BF_FIELD(FS, 13, 2); @@ -233,10 +245,10 @@ public: T old_val = mstatus; auto mask = get_mask(priv_lvl); auto new_val = (old_val & ~mask) | (val & mask); - if ((new_val & mstatus.SXL.Mask) == 0) { + if((new_val & mstatus.SXL.Mask) == 0) { new_val |= old_val & mstatus.SXL.Mask; } - if ((new_val & mstatus.UXL.Mask) == 0) { + if((new_val & mstatus.UXL.Mask) == 0) { new_val |= old_val & mstatus.UXL.Mask; } mstatus = new_val; @@ -248,24 +260,37 @@ public: static constexpr T get_mask(unsigned priv_lvl) { uint64_t ret; - switch (priv_lvl) { - case PRIV_U: ret = 0x8000000f00000011ULL;break; // 0b1...0 1111 0000 0000 0111 1111 1111 1001 1011 1011 - case PRIV_S: ret = 0x8000000f000de133ULL;break; // 0b1...0 0011 0000 0000 0000 1101 1110 0001 0011 0011 - default: ret = 0x8000000f007ff9ddULL;break; // 0b1...0 1111 0000 0000 0111 1111 1111 1001 1011 1011 + switch(priv_lvl) { + case PRIV_U: + ret = 0x8000000f00000011ULL; + break; // 0b1...0 1111 0000 0000 0111 1111 1111 1001 1011 1011 + case PRIV_S: + ret = 0x8000000f000de133ULL; + break; // 0b1...0 0011 0000 0000 0000 1101 1110 0001 0011 0011 + default: + ret = 0x8000000f007ff9ddULL; + break; // 0b1...0 1111 0000 0000 0111 1111 1111 1001 1011 1011 } return ret; } static inline vm_info decode_vm_info(uint32_t state, T sptbr) { - if (state == PRIV_M) return {0, 0, 0, 0}; - if (state <= PRIV_S) - switch (bit_sub<60, 4>(sptbr)) { - case 0: return {0, 0, 0, 0}; // off - case 8: return {3, 9, 8, bit_sub<0, 44>(sptbr) << PGSHIFT};// SV39 - case 9: return {4, 9, 8, bit_sub<0, 44>(sptbr) << PGSHIFT};// SV48 - case 10: return {5, 9, 8, bit_sub<0, 44>(sptbr) << PGSHIFT};// SV57 - case 11: return {6, 9, 8, bit_sub<0, 44>(sptbr) << PGSHIFT};// SV64 - default: abort(); + if(state == PRIV_M) + return {0, 0, 0, 0}; + if(state <= PRIV_S) + switch(bit_sub<60, 4>(sptbr)) { + case 0: + return {0, 0, 0, 0}; // off + case 8: + return {3, 9, 8, bit_sub<0, 44>(sptbr) << PGSHIFT}; // SV39 + case 9: + return {4, 9, 8, bit_sub<0, 44>(sptbr) << PGSHIFT}; // SV48 + case 10: + return {5, 9, 8, bit_sub<0, 44>(sptbr) << PGSHIFT}; // SV57 + case 11: + return {6, 9, 8, bit_sub<0, 44>(sptbr) << PGSHIFT}; // SV64 + default: + abort(); } abort(); return {0, 0, 0, 0}; // dummy @@ -286,19 +311,19 @@ public: return m[mode]; } - riscv_hart_msu_vp(); + riscv_hart_msu_vp(feature_config cfg = feature_config{}); virtual ~riscv_hart_msu_vp() = default; void reset(uint64_t address) override; std::pair load_file(std::string name, int type = -1) override; - phys_addr_t virt2phys(const iss::addr_t &addr) override; + phys_addr_t virt2phys(const iss::addr_t& addr) override; - iss::status read(const address_type type, const access_type access, const uint32_t space, - const uint64_t addr, const unsigned length, uint8_t *const data) override; - iss::status write(const address_type type, const access_type access, const uint32_t space, - const uint64_t addr, const unsigned length, const uint8_t *const data) override; + iss::status read(const address_type type, const access_type access, const uint32_t space, const uint64_t addr, const unsigned length, + uint8_t* const data) override; + iss::status write(const address_type type, const access_type access, const uint32_t space, const uint64_t addr, const unsigned length, + const uint8_t* const data) override; uint64_t enter_trap(uint64_t flags) override { return riscv_hart_msu_vp::enter_trap(flags, fault_data, fault_data); } uint64_t enter_trap(uint64_t flags, uint64_t addr, uint64_t instr) override; @@ -306,28 +331,20 @@ public: void wait_until(uint64_t flags) override; void disass_output(uint64_t pc, const std::string instr) override { - CLOG(INFO, disass) << fmt::format("0x{:016x} {:40} [p:{};s:0x{:x};c:{}]", - pc, instr, lvl[this->reg.PRIV], (reg_t)state.mstatus, this->reg.ccount + cycle_offset); + CLOG(INFO, disass) << fmt::format("0x{:016x} {:40} [p:{};s:0x{:x};c:{}]", pc, instr, lvl[this->reg.PRIV], (reg_t)state.mstatus, + this->reg.icount + cycle_offset); }; - iss::instrumentation_if *get_instrumentation_if() override { return &instr_if; } + iss::instrumentation_if* get_instrumentation_if() override { return &instr_if; } - void setMemReadCb(std::function const& memReadCb) { - mem_read_cb = memReadCb; - } + void set_csr(unsigned addr, reg_t val) { csr[addr & csr.page_addr_mask] = val; } - void setMemWriteCb(std::function const& memWriteCb) { - mem_write_cb = memWriteCb; - } - - void set_csr(unsigned addr, reg_t val){ - csr[addr & csr.page_addr_mask] = val; - } + void set_irq_num(unsigned i) { mcause_max_irq = 1 << util::ilog2(i); } protected: struct riscv_instrumentation_if : public iss::instrumentation_if { - riscv_instrumentation_if(riscv_hart_msu_vp &arch) + riscv_instrumentation_if(riscv_hart_msu_vp& arch) : arch(arch) {} /** * get the name of this architecture @@ -336,27 +353,37 @@ protected: */ const std::string core_type_name() const override { return traits::core_type; } - virtual uint64_t get_pc() { return arch.get_pc(); }; + uint64_t get_pc() override { return arch.reg.PC; } - virtual uint64_t get_next_pc() { return arch.get_next_pc(); }; + uint64_t get_next_pc() override { return arch.reg.NEXT_PC; } - uint64_t get_instr_count() { return arch.reg.icount; } + uint64_t get_instr_word() override { return arch.reg.instruction; } + + uint64_t get_instr_count() override { return arch.reg.icount; } + + uint64_t get_pendig_traps() override { return arch.reg.trap_state; } uint64_t get_total_cycles() override { return arch.reg.icount + arch.cycle_offset; } - virtual void set_curr_instr_cycles(unsigned cycles) { arch.cycle_offset += cycles - 1; }; + void update_last_instr_cycles(unsigned cycles) override { arch.cycle_offset += cycles - 1; } - riscv_hart_msu_vp &arch; + bool is_branch_taken() override { return arch.reg.last_branch; } + + unsigned get_reg_num() override { return traits::NUM_REGS; } + + unsigned get_reg_size(unsigned num) override { return traits::reg_bit_widths[num]; } + + riscv_hart_msu_vp& arch; }; friend struct riscv_instrumentation_if; addr_t get_pc() { return this->reg.PC; } addr_t get_next_pc() { return this->reg.NEXT_PC; } - virtual iss::status read_mem(phys_addr_t addr, unsigned length, uint8_t *const data); - virtual iss::status write_mem(phys_addr_t addr, unsigned length, const uint8_t *const data); + virtual iss::status read_mem(phys_addr_t addr, unsigned length, uint8_t* const data); + virtual iss::status write_mem(phys_addr_t addr, unsigned length, const uint8_t* const data); - virtual iss::status read_csr(unsigned addr, reg_t &val); + virtual iss::status read_csr(unsigned addr, reg_t& val); virtual iss::status write_csr(unsigned addr, reg_t val); hart_state_type state; @@ -383,45 +410,41 @@ protected: std::unordered_map csr_rd_cb; std::unordered_map csr_wr_cb; -private: - iss::status read_reg(unsigned addr, reg_t &val); - iss::status write_reg(unsigned addr, reg_t val); - iss::status read_null(unsigned addr, reg_t &val); - iss::status write_null(unsigned addr, reg_t val){return iss::status::Ok;} - iss::status read_cycle(unsigned addr, reg_t &val); + std::vector tcm; + + iss::status read_csr_reg(unsigned addr, reg_t& val); + iss::status write_csr_reg(unsigned addr, reg_t val); + iss::status read_null(unsigned addr, reg_t& val); + iss::status write_null(unsigned addr, reg_t val) { return iss::status::Ok; } + iss::status read_cycle(unsigned addr, reg_t& val); iss::status write_cycle(unsigned addr, reg_t val); - iss::status read_instret(unsigned addr, reg_t &val); + iss::status read_instret(unsigned addr, reg_t& val); iss::status write_instret(unsigned addr, reg_t val); - iss::status read_mtvec(unsigned addr, reg_t &val); - iss::status read_time(unsigned addr, reg_t &val); - iss::status read_status(unsigned addr, reg_t &val); + iss::status read_tvec(unsigned addr, reg_t& val); + iss::status read_time(unsigned addr, reg_t& val); + iss::status read_status(unsigned addr, reg_t& val); iss::status write_status(unsigned addr, reg_t val); iss::status write_cause(unsigned addr, reg_t val); - iss::status read_ie(unsigned addr, reg_t &val); + iss::status read_ie(unsigned addr, reg_t& val); iss::status write_ie(unsigned addr, reg_t val); - iss::status read_ip(unsigned addr, reg_t &val); - iss::status read_hartid(unsigned addr, reg_t &val); + iss::status read_ip(unsigned addr, reg_t& val); + iss::status write_ideleg(unsigned addr, reg_t val); + iss::status write_edeleg(unsigned addr, reg_t val); + iss::status read_hartid(unsigned addr, reg_t& val); iss::status write_epc(unsigned addr, reg_t val); - iss::status read_satp(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 read_fcsr(unsigned addr, reg_t& val); iss::status write_fcsr(unsigned addr, reg_t val); - virtual iss::status read_custom_csr_reg(unsigned addr, reg_t &val) {return iss::status::Err;}; - virtual iss::status write_custom_csr_reg(unsigned addr, reg_t val) {return iss::status::Err;}; + virtual iss::status read_custom_csr_reg(unsigned addr, reg_t& val) { return iss::status::Err; }; + virtual iss::status write_custom_csr_reg(unsigned addr, reg_t val) { return iss::status::Err; }; - void register_custom_csr_rd(unsigned addr){ - csr_rd_cb[addr] = &this_class::read_custom_csr_reg; - } - void register_custom_csr_wr(unsigned addr){ - csr_wr_cb[addr] = &this_class::write_custom_csr_reg; - } + void register_custom_csr_rd(unsigned addr) { csr_rd_cb[addr] = &this_class::read_custom_csr_reg; } + void register_custom_csr_wr(unsigned addr) { csr_wr_cb[addr] = &this_class::write_custom_csr_reg; } reg_t mhartid_reg{0x0}; - std::functionmem_read_cb; - std::function mem_write_cb; -protected: void check_interrupt(); }; @@ -429,6 +452,7 @@ template riscv_hart_msu_vp::riscv_hart_msu_vp() : state() , instr_if(*this) { + this->_has_mmu = true; // reset values csr[misa] = traits::MISA_VAL; csr[mvendorid] = 0x669; @@ -436,52 +460,56 @@ riscv_hart_msu_vp::riscv_hart_msu_vp() csr[mimpid] = 1; uart_buf.str(""); - for (unsigned addr = mhpmcounter3; addr <= mhpmcounter31; ++addr){ + for(unsigned addr = mhpmcounter3; addr <= mhpmcounter31; ++addr) { csr_rd_cb[addr] = &this_class::read_null; - csr_wr_cb[addr] = &this_class::write_reg; + csr_wr_cb[addr] = &this_class::write_csr_reg; } - for (unsigned addr = mhpmcounter3h; addr <= mhpmcounter31h; ++addr){ + for(unsigned addr = mhpmcounter3h; addr <= mhpmcounter31h; ++addr) { csr_rd_cb[addr] = &this_class::read_null; - csr_wr_cb[addr] = &this_class::write_reg; + csr_wr_cb[addr] = &this_class::write_csr_reg; } - for (unsigned addr = mhpmevent3; addr <= mhpmevent31; ++addr){ + for(unsigned addr = mhpmevent3; addr <= mhpmevent31; ++addr) { csr_rd_cb[addr] = &this_class::read_null; - csr_wr_cb[addr] = &this_class::write_reg; + csr_wr_cb[addr] = &this_class::write_csr_reg; } - for (unsigned addr = hpmcounter3; addr <= hpmcounter31; ++addr){ + for(unsigned addr = hpmcounter3; addr <= hpmcounter31; ++addr) { csr_rd_cb[addr] = &this_class::read_null; } - for (unsigned addr = cycleh; addr <= hpmcounter31h; ++addr){ + for(unsigned addr = cycleh; addr <= hpmcounter31h; ++addr) { csr_rd_cb[addr] = &this_class::read_null; - //csr_wr_cb[addr] = &this_class::write_reg; + // csr_wr_cb[addr] = &this_class::write_csr_reg; } // common regs - const std::array addrs{{ - misa, mvendorid, marchid, mimpid, - mepc, mtvec, mscratch, mcause, mtval, mscratch, - sepc, stvec, sscratch, scause, stval, sscratch, - uepc, utvec, uscratch, ucause, utval, uscratch - }}; - for(auto addr: addrs) { - csr_rd_cb[addr] = &this_class::read_reg; - csr_wr_cb[addr] = &this_class::write_reg; + const std::array addrs{{misa, mvendorid, marchid, mimpid, mepc, mtvec, mscratch, mcause, + mtval, mscratch, sepc, stvec, sscratch, scause, stval, sscratch, + uepc, utvec, uscratch, ucause, utval, uscratch}}; + for(auto addr : addrs) { + csr_rd_cb[addr] = &this_class::read_csr_reg; + csr_wr_cb[addr] = &this_class::write_csr_reg; } // special handling & overrides csr_rd_cb[time] = &this_class::read_time; - csr_rd_cb[timeh] = &this_class::read_time; + if(traits::XLEN == 32) + csr_rd_cb[timeh] = &this_class::read_time; csr_rd_cb[cycle] = &this_class::read_cycle; - csr_rd_cb[cycleh] = &this_class::read_cycle; + if(traits::XLEN == 32) + csr_rd_cb[cycleh] = &this_class::read_cycle; csr_rd_cb[instret] = &this_class::read_instret; - csr_rd_cb[instreth] = &this_class::read_instret; + if(traits::XLEN == 32) + csr_rd_cb[instreth] = &this_class::read_instret; csr_rd_cb[mcycle] = &this_class::read_cycle; csr_wr_cb[mcycle] = &this_class::write_cycle; - csr_rd_cb[mcycleh] = &this_class::read_cycle; - csr_wr_cb[mcycleh] = &this_class::write_cycle; + if(traits::XLEN == 32) + csr_rd_cb[mcycleh] = &this_class::read_cycle; + if(traits::XLEN == 32) + csr_wr_cb[mcycleh] = &this_class::write_cycle; csr_rd_cb[minstret] = &this_class::read_instret; csr_wr_cb[minstret] = &this_class::write_instret; - csr_rd_cb[minstreth] = &this_class::read_instret; - csr_wr_cb[minstreth] = &this_class::write_instret; + if(traits::XLEN == 32) + csr_rd_cb[minstreth] = &this_class::read_instret; + if(traits::XLEN == 32) + csr_wr_cb[minstreth] = &this_class::write_instret; csr_rd_cb[mstatus] = &this_class::read_status; csr_wr_cb[mstatus] = &this_class::write_status; csr_wr_cb[mcause] = &this_class::write_cause; @@ -527,129 +555,137 @@ riscv_hart_msu_vp::riscv_hart_msu_vp() } template std::pair riscv_hart_msu_vp::load_file(std::string name, int type) { - FILE *fp = fopen(name.c_str(), "r"); - if (fp) { + FILE* fp = fopen(name.c_str(), "r"); + if(fp) { std::array buf; auto n = fread(buf.data(), 1, 4, fp); - if (n != 4) throw std::runtime_error("input file has insufficient size"); + fclose(fp); + if(n != 4) + throw std::runtime_error("input file has insufficient size"); buf[4] = 0; - if (strcmp(buf.data() + 1, "ELF") == 0) { - fclose(fp); + if(strcmp(buf.data() + 1, "ELF") == 0) { // Create elfio reader ELFIO::elfio reader; // Load ELF data - if (!reader.load(name)) throw std::runtime_error("could not process elf file"); + if(!reader.load(name)) + throw std::runtime_error("could not process elf file"); // check elf properties - if (reader.get_class() != ELFCLASS32) - if (sizeof(reg_t) == 4) throw std::runtime_error("wrong elf class in file"); - if (reader.get_type() != ET_EXEC) throw std::runtime_error("wrong elf type in file"); - if (reader.get_machine() != EM_RISCV) throw std::runtime_error("wrong elf machine in file"); + if(reader.get_class() != ELFCLASS32) + if(sizeof(reg_t) == 4) + throw std::runtime_error("wrong elf class in file"); + if(reader.get_type() != ET_EXEC) + throw std::runtime_error("wrong elf type in file"); + if(reader.get_machine() != EM_RISCV) + throw std::runtime_error("wrong elf machine in file"); auto entry = reader.get_entry(); - for (const auto pseg : reader.segments) { + for(const auto pseg : reader.segments) { const auto fsize = pseg->get_file_size(); // 0x42c/0x0 const auto seg_data = pseg->get_data(); - if (fsize > 0) { - auto res = this->write(iss::address_type::PHYSICAL, iss::access_type::DEBUG_WRITE, - traits::MEM, pseg->get_physical_address(), - fsize, reinterpret_cast(seg_data)); - if (res != iss::Ok) - LOG(ERROR) << "problem writing " << fsize << "bytes to 0x" << std::hex - << pseg->get_physical_address(); + if(fsize > 0) { + auto res = this->write(iss::address_type::PHYSICAL, iss::access_type::DEBUG_WRITE, traits::MEM, + pseg->get_physical_address(), fsize, reinterpret_cast(seg_data)); + if(res != iss::Ok) + LOG(ERR) << "problem writing " << fsize << "bytes to 0x" << std::hex << pseg->get_physical_address(); } } for(const auto sec : reader.sections) { if(sec->get_name() == ".symtab") { - if ( SHT_SYMTAB == sec->get_type() || - SHT_DYNSYM == sec->get_type() ) { - ELFIO::symbol_section_accessor symbols( reader, sec ); + if(SHT_SYMTAB == sec->get_type() || SHT_DYNSYM == sec->get_type()) { + ELFIO::symbol_section_accessor symbols(reader, sec); auto sym_no = symbols.get_symbols_num(); - std::string name; - ELFIO::Elf64_Addr value = 0; - ELFIO::Elf_Xword size = 0; - unsigned char bind = 0; - unsigned char type = 0; - ELFIO::Elf_Half section = 0; - unsigned char other = 0; - for ( auto i = 0U; i < sym_no; ++i ) { - symbols.get_symbol( i, name, value, size, bind, type, section, other ); - if(name=="tohost") { + std::string name; + ELFIO::Elf64_Addr value = 0; + ELFIO::Elf_Xword size = 0; + unsigned char bind = 0; + unsigned char type = 0; + ELFIO::Elf_Half section = 0; + unsigned char other = 0; + for(auto i = 0U; i < sym_no; ++i) { + symbols.get_symbol(i, name, value, size, bind, type, section, other); + if(name == "tohost") { tohost = value; - } else if(name=="fromhost") { + } else if(name == "fromhost") { fromhost = value; } } } - } else if (sec->get_name() == ".tohost") { + } else if(sec->get_name() == ".tohost") { tohost = sec->get_address(); fromhost = tohost + 0x40; } - } return std::make_pair(entry, true); } - throw std::runtime_error("memory load file is not a valid elf file"); + throw std::runtime_error(fmt::format("memory load file {} is not a valid elf file", name)); } - throw std::runtime_error("memory load file not found"); + throw std::runtime_error(fmt::format("memory load file not found, check if {} is a valid file", name)); } template -iss::status riscv_hart_msu_vp::read(const address_type type, const access_type access, const uint32_t space, - const uint64_t addr, const unsigned length, uint8_t *const data) { +iss::status riscv_hart_msu_vp::read(const address_type type, const access_type access, const uint32_t space, const uint64_t addr, + const unsigned length, uint8_t* const data) { #ifndef NDEBUG - if (access && iss::access_type::DEBUG) { + if(access && iss::access_type::DEBUG) { LOG(TRACEALL) << "debug read of " << length << " bytes @addr 0x" << std::hex << addr; - } else if(access && iss::access_type::FETCH){ + } else if(access && iss::access_type::FETCH) { LOG(TRACEALL) << "fetch of " << length << " bytes @addr 0x" << std::hex << addr; } else { LOG(TRACE) << "read of " << length << " bytes @addr 0x" << std::hex << addr; - } + } #endif try { - switch (space) { + switch(space) { case traits::MEM: { - if (unlikely((access == iss::access_type::FETCH || access == iss::access_type::DEBUG_FETCH) && (addr & 0x1) == 1)) { + auto alignment = is_fetch(access) ? (traits::MISA_VAL & 0x100 ? 2 : 4) : length; + if(unlikely(is_fetch(access) && (addr & (alignment - 1)))) { fault_data = addr; - if (access && iss::access_type::DEBUG) throw trap_access(0, addr); + if(access && iss::access_type::DEBUG) + throw trap_access(0, addr); this->reg.trap_state = (1 << 31); // issue trap 0 return iss::Err; } try { - if (unlikely((addr & ~PGMASK) != ((addr + length - 1) & ~PGMASK))) { // we may cross a page boundary + if(!is_debug(access) && (addr & (alignment - 1))) { + this->reg.trap_state = 1 << 31 | 4 << 16; + fault_data = addr; + return iss::Err; + } + if(unlikely((addr & ~PGMASK) != ((addr + length - 1) & ~PGMASK))) { // we may cross a page boundary vm_info vm = hart_state_type::decode_vm_info(this->reg.PRIV, state.satp); - if (vm.levels != 0) { // VM is active + if(vm.levels != 0) { // VM is active auto split_addr = (addr + length) & ~PGMASK; auto len1 = split_addr - addr; auto res = read(type, access, space, addr, len1, data); - if (res == iss::Ok) + if(res == iss::Ok) res = read(type, access, space, split_addr, length - len1, data + len1); return res; } } - auto res = type==iss::address_type::PHYSICAL? - read_mem( BASE::v2p(phys_addr_t{access, space, addr}), length, data): - read_mem( BASE::v2p(iss::addr_t{access, type, space, addr}), length, data); - if (unlikely(res != iss::Ok)){ - this->reg.trap_state = (1 << 31) | (5 << 16); // issue trap 5 (load access fault - fault_data=addr; + auto res = read_mem(BASE::v2p(iss::addr_t{access, type, space, addr}), length, data); + if(unlikely(res != iss::Ok && (access & access_type::DEBUG) == 0)) { + this->reg.trap_state = (1 << 31) | (5 << 16); // issue trap 5 (load access fault + fault_data = addr; } return res; - } catch (trap_access &ta) { + } catch(trap_access& ta) { this->reg.trap_state = (1 << 31) | ta.id; - fault_data=ta.addr; + fault_data = ta.addr; return iss::Err; } } break; case traits::CSR: { - if (length != sizeof(reg_t)) return iss::Err; - return read_csr(addr, *reinterpret_cast(data)); + if(length != sizeof(reg_t)) + return iss::Err; + return read_csr(addr, *reinterpret_cast(data)); } break; case traits::FENCE: { - if ((addr + length) > mem.size()) return iss::Err; - switch (addr) { + if((addr + length) > mem.size()) + return iss::Err; + switch(addr) { case 2: // SFENCE:VMA lower case 3: { // SFENCE:VMA upper auto tvm = state.mstatus.TVM; - if (this->reg.PRIV == PRIV_S & tvm != 0) { + if(this->reg.PRIV == PRIV_S & tvm != 0) { this->reg.trap_state = (1 << 31) | (2 << 16); this->fault_data = this->reg.PC; return iss::Err; @@ -660,7 +696,7 @@ iss::status riscv_hart_msu_vp::read(const address_type type, const access_ } break; case traits::RES: { auto it = atomic_reservation.find(addr); - if (it != atomic_reservation.end() && it->second != 0) { + if(it != atomic_reservation.end() && it->second != 0) { memset(data, 0xff, length); atomic_reservation.erase(addr); } else @@ -670,81 +706,81 @@ iss::status riscv_hart_msu_vp::read(const address_type type, const access_ return iss::Err; // assert("Not supported"); } return iss::Ok; - } catch (trap_access &ta) { - this->reg.trap_state = (1 << 31) | ta.id; - fault_data=ta.addr; + } catch(trap_access& ta) { + this->reg.trap_state = (1UL << 31) | ta.id; + fault_data = ta.addr; return iss::Err; } } template -iss::status riscv_hart_msu_vp::write(const address_type type, const access_type access, const uint32_t space, - const uint64_t addr, const unsigned length, const uint8_t *const data) { +iss::status riscv_hart_msu_vp::write(const address_type type, const access_type access, const uint32_t space, const uint64_t addr, + const unsigned length, const uint8_t* const data) { #ifndef NDEBUG - const char *prefix = (access && iss::access_type::DEBUG) ? "debug " : ""; - switch (length) { + const char* prefix = (access && iss::access_type::DEBUG) ? "debug " : ""; + switch(length) { case 8: - LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint64_t *)&data[0] << std::dec - << ") @addr 0x" << std::hex << addr; + LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint64_t*)&data[0] << std::dec << ") @addr 0x" + << std::hex << addr; break; case 4: - LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint32_t *)&data[0] << std::dec - << ") @addr 0x" << std::hex << addr; + LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint32_t*)&data[0] << std::dec << ") @addr 0x" + << std::hex << addr; break; case 2: - LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint16_t *)&data[0] << std::dec - << ") @addr 0x" << std::hex << addr; + LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint16_t*)&data[0] << std::dec << ") @addr 0x" + << std::hex << addr; break; case 1: - LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << (uint16_t)data[0] << std::dec - << ") @addr 0x" << std::hex << addr; + LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << (uint16_t)data[0] << std::dec << ") @addr 0x" + << std::hex << addr; break; default: LOG(TRACE) << prefix << "write of " << length << " bytes @addr " << addr; } #endif try { - switch (space) { + switch(space) { case traits::MEM: { - if (unlikely((access && iss::access_type::FETCH) && (addr & 0x1) == 1)) { + if(unlikely((access && iss::access_type::FETCH) && (addr & 0x1) == 1)) { fault_data = addr; - if (access && iss::access_type::DEBUG) throw trap_access(0, addr); + if(access && iss::access_type::DEBUG) + throw trap_access(0, addr); this->reg.trap_state = (1 << 31); // issue trap 0 return iss::Err; } + phys_addr_t paddr = BASE::v2p(iss::addr_t{access, type, space, addr}); try { - if (unlikely((addr & ~PGMASK) != ((addr + length - 1) & ~PGMASK))) { // we may cross a page boundary + if(unlikely((addr & ~PGMASK) != ((addr + length - 1) & ~PGMASK))) { // we may cross a page boundary vm_info vm = hart_state_type::decode_vm_info(this->reg.PRIV, state.satp); - if (vm.levels != 0) { // VM is active + if(vm.levels != 0) { // VM is active auto split_addr = (addr + length) & ~PGMASK; auto len1 = split_addr - addr; auto res = write(type, access, space, addr, len1, data); - if (res == iss::Ok) + if(res == iss::Ok) res = write(type, access, space, split_addr, length - len1, data + len1); return res; } } - auto res = type==iss::address_type::PHYSICAL? - write_mem(phys_addr_t{access, space, addr}, length, data): - write_mem(BASE::v2p(iss::addr_t{access, type, space, addr}), length, data); - if (unlikely(res != iss::Ok)) { - this->reg.trap_state = (1 << 31) | (7 << 16); // issue trap 7 (Store/AMO access fault) - fault_data=addr; + auto res = write_mem(paddr, length, data); + if(unlikely(res != iss::Ok && (access & access_type::DEBUG) == 0)) { + this->reg.trap_state = (1UL << 31) | (7UL << 16); // issue trap 7 (Store/AMO access fault) + fault_data = addr; } return res; - } catch (trap_access &ta) { - this->reg.trap_state = (1 << 31) | ta.id; - fault_data=ta.addr; + } catch(trap_access& ta) { + this->reg.trap_state = (1UL << 31) | ta.id; + fault_data = ta.addr; return iss::Err; } - phys_addr_t paddr = BASE::v2p(iss::addr_t{access, type, space, addr}); - if ((paddr.val + length) > mem.size()) return iss::Err; - switch (paddr.val) { + if((paddr.val + length) > mem.size()) + return iss::Err; + switch(paddr.val) { case 0x10013000: // UART0 base, TXFIFO reg case 0x10023000: // UART1 base, TXFIFO reg uart_buf << (char)data[0]; - if (((char)data[0]) == '\n' || data[0] == 0) { + if(((char)data[0]) == '\n' || data[0] == 0) { // LOG(INFO)<<"UART"<<((paddr.val>>16)&0x3)<<" send // '"<::write(const address_type type, const access } return iss::Ok; case 0x10008000: { // HFROSC base, hfrosccfg reg - auto &p = mem(paddr.val / mem.page_size); + auto& p = mem(paddr.val / mem.page_size); auto offs = paddr.val & mem.page_addr_mask; std::copy(data, data + length, p.data() + offs); - auto &x = *(p.data() + offs + 3); - if (x & 0x40) x |= 0x80; // hfroscrdy = 1 if hfroscen==1 + auto& x = *(p.data() + offs + 3); + if(x & 0x40) + x |= 0x80; // hfroscrdy = 1 if hfroscen==1 return iss::Ok; } case 0x10008008: { // HFROSC base, pllcfg reg - auto &p = mem(paddr.val / mem.page_size); + auto& p = mem(paddr.val / mem.page_size); auto offs = paddr.val & mem.page_addr_mask; std::copy(data, data + length, p.data() + offs); - auto &x = *(p.data() + offs + 3); + auto& x = *(p.data() + offs + 3); x |= 0x80; // set pll lock upon writing return iss::Ok; } break; - default: {} + default: { + } } } break; case traits::CSR: { - if (length != sizeof(reg_t)) return iss::Err; - return write_csr(addr, *reinterpret_cast(data)); + if(length != sizeof(reg_t)) + return iss::Err; + return write_csr(addr, *reinterpret_cast(data)); } break; case traits::FENCE: { - if ((addr + length) > mem.size()) return iss::Err; - switch (addr) { + if((addr + length) > mem.size()) + return iss::Err; + switch(addr) { case 2: case 3: { ptw.clear(); auto tvm = state.mstatus.TVM; - if (this->reg.PRIV == PRIV_S & tvm != 0) { + if(this->reg.PRIV == PRIV_S & tvm != 0) { this->reg.trap_state = (1 << 31) | (2 << 16); this->fault_data = this->reg.PC; return iss::Err; @@ -797,43 +837,45 @@ iss::status riscv_hart_msu_vp::write(const address_type type, const access return iss::Err; } return iss::Ok; - } catch (trap_access &ta) { - this->reg.trap_state = (1 << 31) | ta.id; - fault_data=ta.addr; + } catch(trap_access& ta) { + this->reg.trap_state = (1UL << 31) | ta.id; + fault_data = ta.addr; return iss::Err; } } -template iss::status riscv_hart_msu_vp::read_csr(unsigned addr, reg_t &val) { - if (addr >= csr.size()) return iss::Err; +template iss::status riscv_hart_msu_vp::read_csr(unsigned addr, reg_t& val) { + if(addr >= csr.size()) + return iss::Err; auto req_priv_lvl = (addr >> 8) & 0x3; - if (this->reg.PRIV < req_priv_lvl) // not having required privileges - throw illegal_instruction_fault(this->fault_data); + if(this->reg.PRIV < req_priv_lvl) // not having required privileges + throw illegal_instruction_fault(this->fault_data); auto it = csr_rd_cb.find(addr); - if (it == csr_rd_cb.end() || !it->second) // non existent register + if(it == csr_rd_cb.end() || !it->second) // non existent register throw illegal_instruction_fault(this->fault_data); return (this->*(it->second))(addr, val); } template iss::status riscv_hart_msu_vp::write_csr(unsigned addr, reg_t val) { - if (addr >= csr.size()) return iss::Err; + if(addr >= csr.size()) + return iss::Err; auto req_priv_lvl = (addr >> 8) & 0x3; - if (this->reg.PRIV < req_priv_lvl) // not having required privileges + if(this->reg.PRIV < req_priv_lvl) // not having required privileges throw illegal_instruction_fault(this->fault_data); - if((addr&0xc00)==0xc00) // writing to read-only region + if((addr & 0xc00) == 0xc00) // writing to read-only region throw illegal_instruction_fault(this->fault_data); auto it = csr_wr_cb.find(addr); - if (it == csr_wr_cb.end() || !it->second) // non existent register + if(it == csr_wr_cb.end() || !it->second) // non existent register throw illegal_instruction_fault(this->fault_data); return (this->*(it->second))(addr, val); } -template iss::status riscv_hart_msu_vp::read_reg(unsigned addr, reg_t &val) { +template iss::status riscv_hart_msu_vp::read_reg(unsigned addr, reg_t& val) { val = csr[addr]; return iss::Ok; } -template iss::status riscv_hart_msu_vp::read_null(unsigned addr, reg_t &val) { +template iss::status riscv_hart_msu_vp::read_null(unsigned addr, reg_t& val) { val = 0; return iss::Ok; } @@ -843,76 +885,73 @@ template iss::status riscv_hart_msu_vp::write_reg(unsigned return iss::Ok; } -template iss::status riscv_hart_m_p::read_cycle(unsigned addr, reg_t &val) { +template iss::status riscv_hart_msu_vp::read_cycle(unsigned addr, reg_t& val) { auto cycle_val = this->reg.icount + cycle_offset; - if (addr == mcycle) { + if(addr == mcycle) { val = static_cast(cycle_val); - } else if (addr == mcycleh) { - if (sizeof(typename traits::reg_t) != 4) return iss::Err; + } else if(addr == mcycleh) { + if(sizeof(typename traits::reg_t) != 4) + return iss::Err; val = static_cast(cycle_val >> 32); } return iss::Ok; } -template iss::status riscv_hart_m_p::write_cycle(unsigned addr, reg_t val) { - if (sizeof(typename traits::reg_t) != 4) { - if (addr == mcycleh) - return iss::Err; +template iss::status riscv_hart_msu_vp::write_cycle(unsigned addr, reg_t val) { + if(sizeof(typename traits::reg_t) != 4) { mcycle_csr = static_cast(val); } else { - if (addr == mcycle) { + if(addr == mcycle) { mcycle_csr = (mcycle_csr & 0xffffffff00000000) + val; - } else { - mcycle_csr = (static_cast(val)<<32) + (mcycle_csr & 0xffffffff); + } else { + mcycle_csr = (static_cast(val) << 32) + (mcycle_csr & 0xffffffff); } } - cycle_offset = mcycle_csr-this->reg.icount; // TODO: relying on wrap-around + cycle_offset = mcycle_csr - this->reg.icount; // TODO: relying on wrap-around return iss::Ok; } -template iss::status riscv_hart_m_p::read_instret(unsigned addr, reg_t &val) { - if ((addr&0xff) == (minstret&0xff)) { +template iss::status riscv_hart_msu_vp::read_instret(unsigned addr, reg_t& val) { + if((addr & 0xff) == (minstret & 0xff)) { val = static_cast(this->reg.instret); - } else if ((addr&0xff) == (minstreth&0xff)) { - if (sizeof(typename traits::reg_t) != 4) return iss::Err; + } else if((addr & 0xff) == (minstreth & 0xff)) { val = static_cast(this->reg.instret >> 32); } return iss::Ok; } -template iss::status riscv_hart_m_p::write_instret(unsigned addr, reg_t val) { - if (sizeof(typename traits::reg_t) != 4) { - if ((addr&0xff) == (minstreth&0xff)) - return iss::Err; +template iss::status riscv_hart_msu_vp::write_instret(unsigned addr, reg_t val) { + if(sizeof(typename traits::reg_t) != 4) { this->reg.instret = static_cast(val); } else { - if ((addr&0xff) == (minstret&0xff)) { + if((addr & 0xff) == (minstret & 0xff)) { this->reg.instret = (this->reg.instret & 0xffffffff00000000) + val; - } else { - this->reg.instret = (static_cast(val)<<32) + (this->reg.instret & 0xffffffff); + } else { + this->reg.instret = (static_cast(val) << 32) + (this->reg.instret & 0xffffffff); } } this->reg.instret--; return iss::Ok; } -template iss::status riscv_hart_m_p::read_time(unsigned addr, reg_t &val) { +template iss::status riscv_hart_msu_vp::read_time(unsigned addr, reg_t& val) { uint64_t time_val = this->reg.icount / (100000000 / 32768 - 1); //-> ~3052; - if (addr == time) { + if(addr == time) { val = static_cast(time_val); - } else if (addr == timeh) { - if (sizeof(typename traits::reg_t) != 4) return iss::Err; + } else if(addr == timeh) { + if(sizeof(typename traits::reg_t) != 4) + return iss::Err; val = static_cast(time_val >> 32); } return iss::Ok; } -template iss::status riscv_hart_m_p::read_tvec(unsigned addr, reg_t &val) { +template iss::status riscv_hart_msu_vp::read_tvec(unsigned addr, reg_t& val) { val = csr[addr] & ~2; return iss::Ok; } -template iss::status riscv_hart_msu_vp::read_status(unsigned addr, reg_t &val) { +template iss::status riscv_hart_msu_vp::read_status(unsigned addr, reg_t& val) { auto req_priv_lvl = (addr >> 8) & 0x3; val = state.mstatus & hart_state_type::get_mask(req_priv_lvl); return iss::Ok; @@ -927,18 +966,20 @@ template iss::status riscv_hart_msu_vp::write_status(unsig } template iss::status riscv_hart_msu_vp::write_cause(unsigned addr, reg_t val) { - csr[addr] = val & ((1UL<<(traits::XLEN-1))|0xf); //TODO: make exception code size configurable + csr[addr] = val & ((1UL << (traits::XLEN - 1)) | 0xf); // TODO: make exception code size configurable return iss::Ok; } -template iss::status riscv_hart_msu_vp::read_ie(unsigned addr, reg_t &val) { +template iss::status riscv_hart_msu_vp::read_ie(unsigned addr, reg_t& val) { val = csr[mie]; - if (addr < mie) val &= csr[mideleg]; - if (addr < sie) val &= csr[sideleg]; + if(addr < mie) + val &= csr[mideleg]; + if(addr < sie) + val &= csr[sideleg]; return iss::Ok; } -template iss::status riscv_hart_msu_vp::read_hartid(unsigned addr, reg_t &val) { +template iss::status riscv_hart_msu_vp::read_hartid(unsigned addr, reg_t& val) { val = mhartid_reg; return iss::Ok; } @@ -951,10 +992,12 @@ template iss::status riscv_hart_msu_vp::write_ie(unsigned return iss::Ok; } -template iss::status riscv_hart_msu_vp::read_ip(unsigned addr, reg_t &val) { +template iss::status riscv_hart_msu_vp::read_ip(unsigned addr, reg_t& val) { val = csr[mip]; - if (addr < mip) val &= csr[mideleg]; - if (addr < sip) val &= csr[sideleg]; + if(addr < mip) + val &= csr[mideleg]; + if(addr < sip) + val &= csr[sideleg]; return iss::Ok; } @@ -963,9 +1006,9 @@ template iss::status riscv_hart_msu_vp::write_epc(unsigned return iss::Ok; } -template iss::status riscv_hart_msu_vp::read_satp(unsigned addr, reg_t &val) { +template iss::status riscv_hart_msu_vp::read_satp(unsigned addr, reg_t& val) { reg_t tvm = state.mstatus.TVM; - if (this->reg.PRIV == PRIV_S & tvm != 0) { + if(this->reg.PRIV == PRIV_S & tvm != 0) { this->reg.trap_state = (1 << 31) | (2 << 16); this->fault_data = this->reg.PC; return iss::Err; @@ -976,7 +1019,7 @@ template iss::status riscv_hart_msu_vp::read_satp(unsigned template iss::status riscv_hart_msu_vp::write_satp(unsigned addr, reg_t val) { reg_t tvm = state.mstatus.TVM; - if (this->reg.PRIV == PRIV_S & tvm != 0) { + if(this->reg.PRIV == PRIV_S & tvm != 0) { this->reg.trap_state = (1 << 31) | (2 << 16); this->fault_data = this->reg.PC; return iss::Err; @@ -985,8 +1028,8 @@ template iss::status riscv_hart_msu_vp::write_satp(unsigne update_vm_info(); return iss::Ok; } -template iss::status riscv_hart_msu_vp::read_fcsr(unsigned addr, reg_t &val) { - switch (addr) { +template iss::status riscv_hart_msu_vp::read_fcsr(unsigned addr, reg_t& val) { + switch(addr) { case 1: // fflags, 4:0 val = bit_sub<0, 5>(this->get_fcsr()); break; @@ -1003,7 +1046,7 @@ template iss::status riscv_hart_msu_vp::read_fcsr(unsigned } template iss::status riscv_hart_msu_vp::write_fcsr(unsigned addr, reg_t val) { - switch (addr) { + switch(addr) { case 1: // fflags, 4:0 this->set_fcsr((this->get_fcsr() & 0xffffffe0) | (val & 0x1f)); break; @@ -1019,87 +1062,53 @@ template iss::status riscv_hart_msu_vp::write_fcsr(unsigne return iss::Ok; } -template -iss::status riscv_hart_msu_vp::read_mem(phys_addr_t paddr, unsigned length, uint8_t *const data) { - if(mem_read_cb) return mem_read_cb(paddr, length, data); - switch (paddr.val) { - case 0x0200BFF8: { // CLINT base, mtime reg - if (sizeof(reg_t) < length) return iss::Err; - reg_t time_val; - this->read_csr(time, time_val); - std::copy((uint8_t *)&time_val, ((uint8_t *)&time_val) + length, data); - } break; - case 0x10008000: { - const mem_type::page_type &p = mem(paddr.val / mem.page_size); - uint64_t offs = paddr.val & mem.page_addr_mask; - std::copy(p.data() + offs, p.data() + offs + length, data); - if (this->reg.icount > 30000) data[3] |= 0x80; - } break; +template iss::status riscv_hart_msu_vp::read_mem(phys_addr_t paddr, unsigned length, uint8_t* const data) { + switch(paddr.val) { default: { - for(auto offs=0U; offs -iss::status riscv_hart_msu_vp::write_mem(phys_addr_t paddr, unsigned length, const uint8_t *const data) { - if(mem_write_cb) return mem_write_cb(paddr, length, data); - switch (paddr.val) { - case 0x10013000: // UART0 base, TXFIFO reg - case 0x10023000: // UART1 base, TXFIFO reg - uart_buf << (char)data[0]; - if (((char)data[0]) == '\n' || data[0] == 0) { - // LOG(INFO)<<"UART"<<((paddr.val>>16)&0x3)<<" send - // '"< iss::status riscv_hart_msu_vp::write_mem(phys_addr_t paddr, unsigned length, const uint8_t* const data) { + switch(paddr.val) { + case 0xFFFF0000: // UART0 base, TXFIFO reg + if(((char)data[0]) == '\n' || data[0] == 0) { + LOG(INFO) << "UART" << ((paddr.val >> 12) & 0x3) << " send '" << uart_buf.str() << "'"; uart_buf.str(""); - } + } else if(((char)data[0]) != '\r') + uart_buf << (char)data[0]; break; - case 0x10008000: { // HFROSC base, hfrosccfg reg - mem_type::page_type &p = mem(paddr.val / mem.page_size); - size_t offs = paddr.val & mem.page_addr_mask; - std::copy(data, data + length, p.data() + offs); - uint8_t &x = *(p.data() + offs + 3); - if (x & 0x40) x |= 0x80; // hfroscrdy = 1 if hfroscen==1 - } break; - case 0x10008008: { // HFROSC base, pllcfg reg - mem_type::page_type &p = mem(paddr.val / mem.page_size); - size_t offs = paddr.val & mem.page_addr_mask; - std::copy(data, data + length, p.data() + offs); - uint8_t &x = *(p.data() + offs + 3); - x |= 0x80; // set pll lock upon writing - } break; default: { - mem_type::page_type &p = mem(paddr.val / mem.page_size); + mem_type::page_type& p = mem(paddr.val / mem.page_size); std::copy(data, data + length, p.data() + (paddr.val & mem.page_addr_mask)); // tohost handling in case of riscv-test - if (paddr.access && iss::access_type::FUNC) { - auto tohost_upper = (traits::XLEN == 32 && paddr.val == (tohost + 4)) || - (traits::XLEN == 64 && paddr.val == tohost); - auto tohost_lower = - (traits::XLEN == 32 && paddr.val == tohost) || (traits::XLEN == 64 && paddr.val == tohost); - if (tohost_lower || tohost_upper) { - uint64_t hostvar = *reinterpret_cast(p.data() + (tohost & mem.page_addr_mask)); - if (tohost_upper || (tohost_lower && to_host_wr_cnt > 0)) { - switch (hostvar >> 48) { + if(paddr.access && iss::access_type::FUNC) { + auto tohost_upper = + (traits::XLEN == 32 && paddr.val == (tohost + 4)) || (traits::XLEN == 64 && paddr.val == tohost); + auto tohost_lower = (traits::XLEN == 32 && paddr.val == tohost) || (traits::XLEN == 64 && paddr.val == tohost); + if(tohost_lower || tohost_upper) { + uint64_t hostvar = *reinterpret_cast(p.data() + (tohost & mem.page_addr_mask)); + if(tohost_upper || (tohost_lower && to_host_wr_cnt > 0)) { + switch(hostvar >> 48) { case 0: - if (hostvar != 0x1) { + if(hostvar != 0x1) { LOG(FATAL) << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar << "), stopping simulation"; } else { LOG(INFO) << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar << "), stopping simulation"; } - this->reg.trap_state=std::numeric_limits::max(); - this->interrupt_sim=hostvar; + this->reg.trap_state = std::numeric_limits::max(); + this->interrupt_sim = hostvar; break; - //throw(iss::simulation_stopped(hostvar)); + // throw(iss::simulation_stopped(hostvar)); case 0x0101: { char c = static_cast(hostvar & 0xff); - if (c == '\n' || c == 0) { + if(c == '\n' || c == 0) { LOG(INFO) << "tohost send '" << uart_buf.str() << "'"; uart_buf.str(""); } else @@ -1109,12 +1118,11 @@ iss::status riscv_hart_msu_vp::write_mem(phys_addr_t paddr, unsigned lengt default: break; } - } else if (tohost_lower) + } else if(tohost_lower) to_host_wr_cnt++; - } else if ((traits::XLEN == 32 && paddr.val == fromhost + 4) || - (traits::XLEN == 64 && paddr.val == fromhost)) { - uint64_t fhostvar = *reinterpret_cast(p.data() + (fromhost & mem.page_addr_mask)); - *reinterpret_cast(p.data() + (tohost & mem.page_addr_mask)) = fhostvar; + } else if((traits::XLEN == 32 && paddr.val == fromhost + 4) || (traits::XLEN == 64 && paddr.val == fromhost)) { + uint64_t fhostvar = *reinterpret_cast(p.data() + (fromhost & mem.page_addr_mask)); + *reinterpret_cast(p.data() + (tohost & mem.page_addr_mask)) = fhostvar; } } } @@ -1130,12 +1138,12 @@ template inline void riscv_hart_msu_vp::reset(uint64_t add template inline void riscv_hart_msu_vp::update_vm_info() { vm[1] = hart_state_type::decode_vm_info(this->reg.PRIV, state.satp); - BASE::addr_mode[3]=BASE::addr_mode[2] = vm[1].is_active()? iss::address_type::VIRTUAL : iss::address_type::PHYSICAL; - if (state.mstatus.MPRV) + BASE::addr_mode[3] = BASE::addr_mode[2] = vm[1].is_active() ? iss::address_type::VIRTUAL : iss::address_type::PHYSICAL; + if(state.mstatus.MPRV) vm[0] = hart_state_type::decode_vm_info(state.mstatus.MPP, state.satp); else vm[0] = vm[1]; - BASE::addr_mode[1] = BASE::addr_mode[0]=vm[0].is_active() ? iss::address_type::VIRTUAL : iss::address_type::PHYSICAL; + BASE::addr_mode[1] = BASE::addr_mode[0] = vm[0].is_active() ? iss::address_type::VIRTUAL : iss::address_type::PHYSICAL; ptw.clear(); } @@ -1154,42 +1162,42 @@ template void riscv_hart_msu_vp::check_interrupt() { auto m_enabled = this->reg.PRIV < PRIV_M || (this->reg.PRIV == PRIV_M && mie); auto enabled_interrupts = m_enabled ? ena_irq & ~ideleg : 0; - if (enabled_interrupts == 0) { + if(enabled_interrupts == 0) { auto sie = state.mstatus.SIE; auto s_enabled = this->reg.PRIV < PRIV_S || (this->reg.PRIV == PRIV_S && sie); enabled_interrupts = s_enabled ? ena_irq & ideleg : 0; } - if (enabled_interrupts != 0) { + if(enabled_interrupts != 0) { int res = 0; - while ((enabled_interrupts & 1) == 0) enabled_interrupts >>= 1, res++; + while((enabled_interrupts & 1) == 0) + enabled_interrupts >>= 1, res++; this->reg.pending_trap = res << 16 | 1; // 0x80 << 24 | (cause << 16) | trap_id } } -template -typename riscv_hart_msu_vp::phys_addr_t riscv_hart_msu_vp::virt2phys(const iss::addr_t &addr) { +template typename riscv_hart_msu_vp::phys_addr_t riscv_hart_msu_vp::virt2phys(const iss::addr_t& addr) { const auto type = addr.access & iss::access_type::FUNC; auto it = ptw.find(addr.val >> PGSHIFT); - if (it != ptw.end()) { + if(it != ptw.end()) { const reg_t pte = it->second; const reg_t ad = PTE_A | (type == iss::access_type::WRITE) * PTE_D; #ifdef RISCV_ENABLE_DIRTY // set accessed and possibly dirty bits. - *(uint32_t *)ppte |= ad; + *(uint32_t*)ppte |= ad; return {addr.getAccessType(), addr.space, (pte & (~PGMASK)) | (addr.val & PGMASK)}; #else // take exception if access or possibly dirty bit is not set. - if ((pte & ad) == ad) + if((pte & ad) == ad) return {addr.access, addr.space, (pte & (~PGMASK)) | (addr.val & PGMASK)}; else ptw.erase(it); // throw an exception #endif } else { uint32_t mode = type != iss::access_type::FETCH && state.mstatus.MPRV ? // MPRV - state.mstatus.MPP : - this->reg.PRIV; + state.mstatus.MPP + : this->reg.PRIV; - const vm_info &vm = this->vm[static_cast(type) / 2]; + const vm_info& vm = this->vm[static_cast(type) / 2]; const bool s_mode = mode == PRIV_S; const bool sum = state.mstatus.SUM; @@ -1202,38 +1210,39 @@ typename riscv_hart_msu_vp::phys_addr_t riscv_hart_msu_vp::virt2phys const int levels = (masked_msbs != 0 && masked_msbs != mask) ? 0 : vm.levels; reg_t base = vm.ptbase; - for (int i = levels - 1; i >= 0; i--) { + for(int i = levels - 1; i >= 0; i--) { const int ptshift = i * vm.idxbits; const reg_t idx = (addr.val >> (PGSHIFT + ptshift)) & ((1 << vm.idxbits) - 1); // check that physical address of PTE is legal reg_t pte = 0; - const uint8_t res = this->read(iss::address_type::PHYSICAL, addr.access, - traits::MEM, base + idx * vm.ptesize, vm.ptesize, (uint8_t *)&pte); - if (res != 0) throw trap_load_access_fault(addr.val); + const uint8_t res = this->read(iss::address_type::PHYSICAL, addr.access, traits::MEM, base + idx * vm.ptesize, vm.ptesize, + (uint8_t*)&pte); + if(res != 0) + throw trap_load_access_fault(addr.val); const reg_t ppn = pte >> PTE_PPN_SHIFT; - if (PTE_TABLE(pte)) { // next level of page table + if(PTE_TABLE(pte)) { // next level of page table base = ppn << PGSHIFT; - } else if ((pte & PTE_U) ? s_mode && (type == iss::access_type::FETCH || !sum) : !s_mode) { + } else if((pte & PTE_U) ? s_mode && (type == iss::access_type::FETCH || !sum) : !s_mode) { break; - } else if (!(pte & PTE_V) || (!(pte & PTE_R) && (pte & PTE_W))) { + } else if(!(pte & PTE_V) || (!(pte & PTE_R) && (pte & PTE_W))) { break; - } else if (type == iss::access_type::FETCH - ? !(pte & PTE_X) - : type == iss::access_type::READ ? !(pte & PTE_R) && !(mxr && (pte & PTE_X)) - : !((pte & PTE_R) && (pte & PTE_W))) { + } else if(type == (iss::access_type::FETCH ? !(pte & PTE_X) + : type == iss::access_type::READ ? !(pte & PTE_R) && !(mxr && (pte & PTE_X)) + : !((pte & PTE_R) && (pte & PTE_W)))) { break; - } else if ((ppn & ((reg_t(1) << ptshift) - 1)) != 0) { + } else if((ppn & ((reg_t(1) << ptshift) - 1)) != 0) { break; } else { const reg_t ad = PTE_A | ((type == iss::access_type::WRITE) * PTE_D); #ifdef RISCV_ENABLE_DIRTY // set accessed and possibly dirty bits. - *(uint32_t *)ppte |= ad; + *(uint32_t*)ppte |= ad; #else // take exception if access or possibly dirty bit is not set. - if ((pte & ad) != ad) break; + if((pte & ad) != ad) + break; #endif // for superpage mappings, make a fake leaf PTE for the TLB's benefit. const reg_t vpn = addr.val >> PGSHIFT; @@ -1244,7 +1253,7 @@ typename riscv_hart_msu_vp::phys_addr_t riscv_hart_msu_vp::virt2phys } } } - switch (type) { + switch(type) { case access_type::FETCH: this->fault_data = addr.val; throw trap_instruction_page_fault(addr.val); @@ -1263,13 +1272,16 @@ template uint64_t riscv_hart_msu_vp::enter_trap(uint64_t f auto cur_priv = this->reg.PRIV; // flags are ACTIVE[31:31], CAUSE[30:16], TRAPID[15:0] // calculate and write mcause val + if(flags == std::numeric_limits::max()) + flags = this->reg.trap_state; auto trap_id = bit_sub<0, 16>(flags); auto cause = bit_sub<16, 15>(flags); - if (trap_id == 0 && cause == 11) cause = 0x8 + cur_priv; // adjust environment call cause + if(trap_id == 0 && cause == 11) + cause = 0x8 + cur_priv; // adjust environment call cause // calculate effective privilege level auto new_priv = PRIV_M; - if (trap_id == 0) { // exception - if (cur_priv != PRIV_M && ((csr[medeleg] >> cause) & 0x1) != 0) + if(trap_id == 0) { // exception + if(cur_priv != PRIV_M && ((csr[medeleg] >> cause) & 0x1) != 0) new_priv = (csr[sedeleg] >> cause) & 0x1 ? PRIV_U : PRIV_S; // store ret addr in xepc register csr[uepc | (new_priv << 8)] = static_cast(addr); // store actual address instruction of exception @@ -1280,15 +1292,15 @@ template uint64_t riscv_hart_msu_vp::enter_trap(uint64_t f * access, or page-fault exception occurs, mtval is written with the * faulting effective address. */ - switch(cause){ + switch(cause) { case 0: csr[utval | (new_priv << 8)] = static_cast(addr); break; case 2: - csr[utval | (new_priv << 8)] = (instr & 0x3)==3?instr:instr&0xffff; + csr[utval | (new_priv << 8)] = (instr & 0x3) == 3 ? instr : instr & 0xffff; break; case 3: - //TODO: implement debug mode behavior + // TODO: implement debug mode behavior // csr[dpc] = addr; // csr[dcsr] = (csr[dcsr] & ~0x1c3) | (1<<6) | PRIV_M; //FIXME: cause should not be 4 (stepi) csr[utval | (new_priv << 8)] = addr; @@ -1303,7 +1315,7 @@ template uint64_t riscv_hart_msu_vp::enter_trap(uint64_t f } fault_data = 0; } else { - if (cur_priv != PRIV_M && ((csr[mideleg] >> cause) & 0x1) != 0) + if(cur_priv != PRIV_M && ((csr[mideleg] >> cause) & 0x1) != 0) new_priv = (csr[sideleg] >> cause) & 0x1 ? PRIV_U : PRIV_S; csr[uepc | (new_priv << 8)] = this->reg.NEXT_PC; // store next address if interrupt this->reg.pending_trap = 0; @@ -1317,7 +1329,7 @@ template uint64_t riscv_hart_msu_vp::enter_trap(uint64_t f // the trap; and the x IE field of mstatus // is cleared // store the actual privilege level in yPP and store interrupt enable flags - switch (new_priv) { + switch(new_priv) { case PRIV_M: state.mstatus.MPP = cur_priv; state.mstatus.MPIE = state.mstatus.MIE; @@ -1341,14 +1353,15 @@ template uint64_t riscv_hart_msu_vp::enter_trap(uint64_t f // calculate addr// set NEXT_PC to trap addressess to jump to based on MODE // bits in mtvec this->reg.NEXT_PC = ivec & ~0x3UL; - if ((ivec & 0x1) == 1 && trap_id != 0) this->reg.NEXT_PC += 4 * cause; + if((ivec & 0x1) == 1 && trap_id != 0) + this->reg.NEXT_PC += 4 * cause; std::array buffer; sprintf(buffer.data(), "0x%016lx", addr); - if((flags&0xffffffff) != 0xffffffff) - CLOG(INFO, disass) << (trap_id ? "Interrupt" : "Trap") << " with cause '" - << (trap_id ? irq_str[cause] : trap_str[cause]) << "' (" << cause << ")" - << " at address " << buffer.data() << " occurred, changing privilege level from " - << lvl[cur_priv] << " to " << lvl[new_priv]; + if((flags & 0xffffffff) != 0xffffffff) + CLOG(INFO, disass) << (trap_id ? "Interrupt" : "Trap") << " with cause '" << (trap_id ? irq_str[cause] : trap_str[cause]) << "' (" + << cause << ")" + << " at address " << buffer.data() << " occurred, changing privilege level from " << lvl[cur_priv] << " to " + << lvl[new_priv]; // reset trap state this->reg.PRIV = new_priv; this->reg.trap_state = 0; @@ -1362,7 +1375,7 @@ template uint64_t riscv_hart_msu_vp::leave_trap(uint64_t f auto status = state.mstatus; auto tsr = state.mstatus.TSR; - if (cur_priv == PRIV_S && inst_priv == PRIV_S && tsr != 0) { + if(cur_priv == PRIV_S && inst_priv == PRIV_S && tsr != 0) { this->reg.trap_state = (1 << 31) | (2 << 16); this->fault_data = this->reg.PC; return this->reg.PC; @@ -1370,7 +1383,7 @@ template uint64_t riscv_hart_msu_vp::leave_trap(uint64_t f // pop the relevant lower-privilege interrupt enable and privilege mode stack // clear respective yIE - switch (inst_priv) { + switch(inst_priv) { case PRIV_M: this->reg.PRIV = state.mstatus.MPP; state.mstatus.MPP = 0; // clear mpp to U mode @@ -1391,8 +1404,7 @@ template uint64_t riscv_hart_msu_vp::leave_trap(uint64_t f } // sets the pc to the value stored in the x epc register. this->reg.NEXT_PC = csr[uepc | inst_priv << 8]; - CLOG(INFO, disass) << "Executing xRET , changing privilege level from " << lvl[cur_priv] << " to " - << lvl[this->reg.PRIV]; + CLOG(INFO, disass) << "Executing xRET , changing privilege level from " << lvl[cur_priv] << " to " << lvl[this->reg.PRIV]; update_vm_info(); check_interrupt(); return this->reg.NEXT_PC; @@ -1401,12 +1413,12 @@ template uint64_t riscv_hart_msu_vp::leave_trap(uint64_t f template void riscv_hart_msu_vp::wait_until(uint64_t flags) { auto status = state.mstatus; auto tw = status.TW; - if (this->reg.PRIV == PRIV_S && tw != 0) { + if(this->reg.PRIV == PRIV_S && tw != 0) { this->reg.trap_state = (1 << 31) | (2 << 16); this->fault_data = this->reg.PC; } } -} -} +} // namespace arch +} // namespace iss #endif /* _RISCV_HART_MSU_VP_H */ diff --git a/src/iss/arch/riscv_hart_mu_p.h b/src/iss/arch/riscv_hart_mu_p.h new file mode 100644 index 0000000..7aa8b21 --- /dev/null +++ b/src/iss/arch/riscv_hart_mu_p.h @@ -0,0 +1,1583 @@ +/******************************************************************************* + * Copyright (C) 2017 - 2023 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 implementation + ******************************************************************************/ + +#ifndef _RISCV_HART_MU_P_H +#define _RISCV_HART_MU_P_H + +#include "iss/arch/traits.h" +#include "iss/instrumentation_if.h" +#include "iss/log_categories.h" +#include "iss/vm_if.h" +#include "riscv_hart_common.h" +#ifndef FMT_HEADER_ONLY +#define FMT_HEADER_ONLY +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(__GNUC__) +#define likely(x) __builtin_expect(!!(x), 1) +#define unlikely(x) __builtin_expect(!!(x), 0) +#else +#define likely(x) x +#define unlikely(x) x +#endif + +namespace iss { +namespace arch { + +template class riscv_hart_mu_p : public BASE { +protected: + const std::array lvl = {{'U', 'S', 'H', 'M'}}; + const std::array trap_str = {{"" + "Instruction address misaligned", // 0 + "Instruction access fault", // 1 + "Illegal instruction", // 2 + "Breakpoint", // 3 + "Load address misaligned", // 4 + "Load access fault", // 5 + "Store/AMO address misaligned", // 6 + "Store/AMO access fault", // 7 + "Environment call from U-mode", // 8 + "Environment call from S-mode", // 9 + "Reserved", // a + "Environment call from M-mode", // b + "Instruction page fault", // c + "Load page fault", // d + "Reserved", // e + "Store/AMO page fault"}}; + const std::array irq_str = {{"User software interrupt", "Supervisor software interrupt", "Reserved", + "Machine software interrupt", "User timer interrupt", "Supervisor timer interrupt", + "Reserved", "Machine timer interrupt", "User external interrupt", + "Supervisor external interrupt", "Reserved", "Machine external interrupt"}}; + +public: + using core = BASE; + using this_class = riscv_hart_mu_p; + using phys_addr_t = typename core::phys_addr_t; + using reg_t = typename core::reg_t; + using addr_t = typename core::addr_t; + + using rd_csr_f = iss::status (this_class::*)(unsigned addr, reg_t&); + using wr_csr_f = iss::status (this_class::*)(unsigned addr, reg_t); + using mem_read_f = iss::status(phys_addr_t addr, unsigned, uint8_t* const); + using mem_write_f = iss::status(phys_addr_t addr, unsigned, uint8_t const* const); + + // primary template + template struct hart_state {}; + // specialization 32bit + template class hart_state::value>::type> { + public: + BEGIN_BF_DECL(mstatus_t, T); + // SD bit is read-only and is set when either the FS or XS bits encode a Dirty state (i.e., SD=((FS==11) OR + // XS==11))) + BF_FIELD(SD, 31, 1); + // Trap SRET + BF_FIELD(TSR, 22, 1); + // Timeout Wait + BF_FIELD(TW, 21, 1); + // Trap Virtual Memory + BF_FIELD(TVM, 20, 1); + // Make eXecutable Readable + BF_FIELD(MXR, 19, 1); + // permit Supervisor User Memory access + BF_FIELD(SUM, 18, 1); + // Modify PRiVilege + BF_FIELD(MPRV, 17, 1); + // status of additional user-mode extensions and associated state, All off/None dirty or clean, some on/None + // dirty, some clean/Some dirty + BF_FIELD(XS, 15, 2); + // floating-point unit status Off/Initial/Clean/Dirty + BF_FIELD(FS, 13, 2); + // machine previous privilege + BF_FIELD(MPP, 11, 2); + // supervisor previous privilege + BF_FIELD(SPP, 8, 1); + // previous machine interrupt-enable + BF_FIELD(MPIE, 7, 1); + // previous supervisor interrupt-enable + BF_FIELD(SPIE, 5, 1); + // previous user interrupt-enable + BF_FIELD(UPIE, 4, 1); + // machine interrupt-enable + BF_FIELD(MIE, 3, 1); + // supervisor interrupt-enable + BF_FIELD(SIE, 1, 1); + // user interrupt-enable + BF_FIELD(UIE, 0, 1); + END_BF_DECL(); + + mstatus_t mstatus; + + static const reg_t mstatus_reset_val = 0x1800; // MPP set to 1 + + void write_mstatus(T val, unsigned priv_lvl) { + auto mask = get_mask(priv_lvl); + auto new_val = (mstatus.backing.val & ~mask) | (val & mask); + mstatus = new_val; + } + + static constexpr uint32_t get_mask(unsigned priv_lvl) { +#if __cplusplus < 201402L + return priv_lvl == PRIV_U ? 0x80000011UL : priv_lvl == PRIV_S ? 0x800de133UL : 0x807ff9ddUL; +#else + switch(priv_lvl) { + case PRIV_U: + return 0x00000011UL; // 0b1000 0000 0000 0000 0000 0000 0001 0001 + default: + // +-SD + // | +-TSR + // | |+-TW + // | ||+-TVM + // | |||+-MXR + // | ||||+-SUM + // | |||||+-MPRV + // | |||||| +-XS + // | |||||| | +-FS + // | |||||| | | +-MPP + // | |||||| | | | +-SPP + // | |||||| | | | |+-MPIE + // | |||||| | | | || +-UPIE + // | ||||||/|/|/| || |+-MIE + // | ||||||/|/|/| || || +-UIE + return 0b00000000000000000001100010011001; + } +#endif + } + }; + + // specialization 64bit + template class hart_state::value>::type> { + public: + BEGIN_BF_DECL(mstatus_t, T); + // SD bit is read-only and is set when either the FS or XS bits encode a Dirty state (i.e., SD=((FS==11) OR + // XS==11))) + BF_FIELD(SD, 63, 1); + // value of XLEN for S-mode + BF_FIELD(SXL, 34, 2); + // value of XLEN for U-mode + BF_FIELD(UXL, 32, 2); + // Trap SRET + BF_FIELD(TSR, 22, 1); + // Timeout Wait + BF_FIELD(TW, 21, 1); + // Trap Virtual Memory + BF_FIELD(TVM, 20, 1); + // Make eXecutable Readable + BF_FIELD(MXR, 19, 1); + // permit Supervisor User Memory access + BF_FIELD(SUM, 18, 1); + // Modify PRiVilege + BF_FIELD(MPRV, 17, 1); + // status of additional user-mode extensions and associated state, All off/None dirty or clean, some on/None + // dirty, some clean/Some dirty + BF_FIELD(XS, 15, 2); + // floating-point unit status Off/Initial/Clean/Dirty + BF_FIELD(FS, 13, 2); + // machine previous privilege + BF_FIELD(MPP, 11, 2); + // supervisor previous privilege + BF_FIELD(SPP, 8, 1); + // previous machine interrupt-enable + BF_FIELD(MPIE, 7, 1); + // previous supervisor interrupt-enable + BF_FIELD(SPIE, 5, 1); + // previous user interrupt-enable + BF_FIELD(UPIE, 4, 1); + // machine interrupt-enable + BF_FIELD(MIE, 3, 1); + // supervisor interrupt-enable + BF_FIELD(SIE, 1, 1); + // user interrupt-enable + BF_FIELD(UIE, 0, 1); + END_BF_DECL(); + + mstatus_t mstatus; + + static const reg_t mstatus_reset_val = 0x1800; + + void write_mstatus(T val, unsigned priv_lvl) { + auto mask = get_mask(priv_lvl); + auto new_val = (mstatus.backing.val & ~mask) | (val & mask); + mstatus = new_val; + } + + static constexpr uint64_t get_mask(unsigned priv_lvl) { +#if __cplusplus < 201402L + return priv_lvl == PRIV_U ? 0x011ULL : priv_lvl == PRIV_S ? 0x000de133ULL : 0x007ff9ddULL; +#else + switch(priv_lvl) { + case PRIV_U: + return 0x00000011UL; // 0b1000 0000 0000 0000 0000 0000 0001 0001 + default: + // +-SD + // | +-TSR + // | |+-TW + // | ||+-TVM + // | |||+-MXR + // | ||||+-SUM + // | |||||+-MPRV + // | |||||| +-XS + // | |||||| | +-FS + // | |||||| | | +-MPP + // | |||||| | | | +-SPP + // | |||||| | | | |+-MPIE + // | |||||| | | | || +-UPIE + // | ||||||/|/|/| || |+-MIE + // | ||||||/|/|/| || || +-UIE + return 0b00000000000000000001100010011001; + } +#endif + } + }; + + using hart_state_type = hart_state; + + constexpr reg_t get_irq_mask(size_t mode) { + std::array m = {{ + 0b000100010001, // U mode + 0b001100110011, // S mode + 0, + 0b100110011001 // M mode + }}; + return m[mode]; + } + + constexpr bool has_compressed() { return traits::MISA_VAL & 0b0100; } + constexpr reg_t get_pc_mask() { return has_compressed() ? ~1 : ~3; } + + riscv_hart_mu_p(feature_config cfg = feature_config{}); + + virtual ~riscv_hart_mu_p() = default; + + void reset(uint64_t address) override; + + std::pair load_file(std::string name, int type = -1) override; + + iss::status read(const address_type type, const access_type access, const uint32_t space, const uint64_t addr, const unsigned length, + uint8_t* const data) override; + iss::status write(const address_type type, const access_type access, const uint32_t space, const uint64_t addr, const unsigned length, + const uint8_t* const data) override; + + uint64_t enter_trap(uint64_t flags) override { return riscv_hart_mu_p::enter_trap(flags, fault_data, fault_data); } + uint64_t enter_trap(uint64_t flags, uint64_t addr, uint64_t instr) override; + uint64_t leave_trap(uint64_t flags) override; + + const reg_t& get_mhartid() const { return mhartid_reg; } + void set_mhartid(reg_t mhartid) { mhartid_reg = mhartid; }; + + void disass_output(uint64_t pc, const std::string instr) override { + CLOG(INFO, disass) << fmt::format("0x{:016x} {:40} [p:{};s:0x{:x};c:{}]", pc, instr, lvl[this->reg.PRIV], (reg_t)state.mstatus, + this->reg.icount + cycle_offset); + }; + + iss::instrumentation_if* get_instrumentation_if() override { return &instr_if; } + + void set_csr(unsigned addr, reg_t val) { csr[addr & csr.page_addr_mask] = val; } + + void set_irq_num(unsigned i) { mcause_max_irq = 1 << util::ilog2(i); } + +protected: + struct riscv_instrumentation_if : public iss::instrumentation_if { + + riscv_instrumentation_if(riscv_hart_mu_p& arch) + : arch(arch) {} + /** + * get the name of this architecture + * + * @return the name of this architecture + */ + const std::string core_type_name() const override { return traits::core_type; } + + uint64_t get_pc() override { return arch.reg.PC; } + + uint64_t get_next_pc() override { return arch.reg.NEXT_PC; } + + uint64_t get_instr_word() override { return arch.reg.instruction; } + + uint64_t get_instr_count() override { return arch.reg.icount; } + + uint64_t get_pendig_traps() override { return arch.reg.trap_state; } + + uint64_t get_total_cycles() override { return arch.reg.icount + arch.cycle_offset; } + + void update_last_instr_cycles(unsigned cycles) override { arch.cycle_offset += cycles - 1; } + + bool is_branch_taken() override { return arch.reg.last_branch; } + + unsigned get_reg_num() override { return traits::NUM_REGS; } + + unsigned get_reg_size(unsigned num) override { return traits::reg_bit_widths[num]; } + + riscv_hart_mu_p& arch; + }; + + friend struct riscv_instrumentation_if; + + virtual iss::status read_mem(phys_addr_t addr, unsigned length, uint8_t* const data); + virtual iss::status write_mem(phys_addr_t addr, unsigned length, const uint8_t* const data); + + iss::status read_clic(uint64_t addr, unsigned length, uint8_t* const data); + iss::status write_clic(uint64_t addr, unsigned length, const uint8_t* const data); + + virtual iss::status read_csr(unsigned addr, reg_t& val); + virtual iss::status write_csr(unsigned addr, reg_t val); + + hart_state_type state; + int64_t cycle_offset{0}; + uint64_t mcycle_csr{0}; + int64_t instret_offset{0}; + uint64_t minstret_csr{0}; + reg_t fault_data; + uint64_t tohost = tohost_dflt; + uint64_t fromhost = fromhost_dflt; + unsigned to_host_wr_cnt = 0; + riscv_instrumentation_if instr_if; + + using mem_type = util::sparse_array; + using csr_type = util::sparse_array::reg_t, 1ULL << 12, 12>; + using csr_page_type = typename csr_type::page_type; + mem_type mem; + csr_type csr; + std::stringstream uart_buf; + std::unordered_map ptw; + std::unordered_map atomic_reservation; + std::unordered_map csr_rd_cb; + std::unordered_map csr_wr_cb; + uint8_t clic_cfg_reg{0}; + std::array clic_inttrig_reg; + union clic_int_reg_t { + struct { + uint8_t ip; + uint8_t ie; + uint8_t attr; + uint8_t ctl; + }; + uint32_t raw; + }; + std::vector clic_int_reg; + uint8_t clic_mprev_lvl{0}, clic_uprev_lvl{0}; + uint8_t clic_mact_lvl{0}, clic_uact_lvl{0}; + + std::vector tcm; + + iss::status read_csr_reg(unsigned addr, reg_t& val); + iss::status write_csr_reg(unsigned addr, reg_t val); + iss::status read_null(unsigned addr, reg_t& val); + iss::status write_null(unsigned addr, reg_t val) { return iss::status::Ok; } + iss::status read_cycle(unsigned addr, reg_t& val); + iss::status write_cycle(unsigned addr, reg_t val); + iss::status read_instret(unsigned addr, reg_t& val); + iss::status write_instret(unsigned addr, reg_t val); + iss::status read_tvec(unsigned addr, reg_t& val); + iss::status read_time(unsigned addr, reg_t& val); + iss::status read_status(unsigned addr, reg_t& val); + iss::status write_status(unsigned addr, reg_t val); + iss::status read_cause(unsigned addr, reg_t& val); + iss::status write_cause(unsigned addr, reg_t val); + iss::status read_ie(unsigned addr, reg_t& val); + iss::status write_ie(unsigned addr, reg_t val); + iss::status read_ip(unsigned addr, reg_t& val); + iss::status write_ideleg(unsigned addr, reg_t val); + iss::status write_edeleg(unsigned addr, reg_t val); + iss::status read_hartid(unsigned addr, reg_t& val); + iss::status write_epc(unsigned addr, reg_t val); + iss::status read_intstatus(unsigned addr, reg_t& val); + iss::status write_intthresh(unsigned addr, reg_t val); + iss::status write_xtvt(unsigned addr, reg_t val); + iss::status write_dcsr_dcsr(unsigned addr, reg_t val); + iss::status read_dcsr_reg(unsigned addr, reg_t& val); + iss::status write_dcsr_reg(unsigned addr, reg_t val); + iss::status read_dpc_reg(unsigned addr, reg_t& val); + iss::status write_dpc_reg(unsigned addr, reg_t val); + iss::status write_pmpcfg_reg(unsigned addr, reg_t val); + + virtual iss::status read_custom_csr_reg(unsigned addr, reg_t& val) { return iss::status::Err; }; + virtual iss::status write_custom_csr_reg(unsigned addr, reg_t val) { return iss::status::Err; }; + + void register_custom_csr_rd(unsigned addr) { csr_rd_cb[addr] = &this_class::read_custom_csr_reg; } + void register_custom_csr_wr(unsigned addr) { csr_wr_cb[addr] = &this_class::write_custom_csr_reg; } + + reg_t mhartid_reg{0x0}; + + void check_interrupt(); + bool pmp_check(const access_type type, const uint64_t addr, const unsigned len); + std::vector> memfn_range; + std::vector> memfn_read; + std::vector> memfn_write; + void insert_mem_range(uint64_t, uint64_t, std::function, std::function); + feature_config cfg; + unsigned mcause_max_irq{(FEAT & features_e::FEAT_CLIC) ? std::max(16U, static_cast(traits::CLIC_NUM_IRQ)) : 16U}; + inline bool debug_mode_active() { return this->reg.PRIV & 0x4; } + + std::pair, std::function> replace_mem_access(std::function rd, + std::function wr) { + std::pair, std::function> ret{hart_mem_rd_delegate, hart_mem_wr_delegate}; + hart_mem_rd_delegate = rd; + hart_mem_wr_delegate = wr; + return ret; + } + std::function hart_mem_rd_delegate; + std::function hart_mem_wr_delegate; +}; + +template +riscv_hart_mu_p::riscv_hart_mu_p(feature_config cfg) +: state() +, instr_if(*this) +, cfg(cfg) { + // reset values + csr[misa] = traits::MISA_VAL; + csr[mvendorid] = 0x669; + csr[marchid] = traits::MARCHID_VAL; + csr[mimpid] = 1; + + uart_buf.str(""); + for(unsigned addr = mhpmcounter3; addr <= mhpmcounter31; ++addr) { + csr_rd_cb[addr] = &this_class::read_null; + csr_wr_cb[addr] = &this_class::write_csr_reg; + } + if(traits::XLEN == 32) + for(unsigned addr = mhpmcounter3h; addr <= mhpmcounter31h; ++addr) { + csr_rd_cb[addr] = &this_class::read_null; + csr_wr_cb[addr] = &this_class::write_csr_reg; + } + for(unsigned addr = mhpmevent3; addr <= mhpmevent31; ++addr) { + csr_rd_cb[addr] = &this_class::read_null; + csr_wr_cb[addr] = &this_class::write_csr_reg; + } + for(unsigned addr = hpmcounter3; addr <= hpmcounter31; ++addr) { + csr_rd_cb[addr] = &this_class::read_null; + } + if(traits::XLEN == 32) + for(unsigned addr = hpmcounter3h; addr <= hpmcounter31h; ++addr) { + csr_rd_cb[addr] = &this_class::read_null; + // csr_wr_cb[addr] = &this_class::write_csr_reg; + } + // common regs + const std::array roaddrs{{misa, mvendorid, marchid, mimpid}}; + for(auto addr : roaddrs) { + csr_rd_cb[addr] = &this_class::read_csr_reg; + csr_wr_cb[addr] = &this_class::write_null; + } + const std::array rwaddrs{{ + mepc, + mtvec, + mscratch, + mtval, + uepc, + utvec, + uscratch, + utval, + }}; + for(auto addr : rwaddrs) { + csr_rd_cb[addr] = &this_class::read_csr_reg; + csr_wr_cb[addr] = &this_class::write_csr_reg; + } + // special handling & overrides + csr_rd_cb[time] = &this_class::read_time; + if(traits::XLEN == 32) + csr_rd_cb[timeh] = &this_class::read_time; + csr_rd_cb[cycle] = &this_class::read_cycle; + if(traits::XLEN == 32) + csr_rd_cb[cycleh] = &this_class::read_cycle; + csr_rd_cb[instret] = &this_class::read_instret; + if(traits::XLEN == 32) + csr_rd_cb[instreth] = &this_class::read_instret; + + csr_rd_cb[mcycle] = &this_class::read_cycle; + csr_wr_cb[mcycle] = &this_class::write_cycle; + if(traits::XLEN == 32) + csr_rd_cb[mcycleh] = &this_class::read_cycle; + if(traits::XLEN == 32) + csr_wr_cb[mcycleh] = &this_class::write_cycle; + csr_rd_cb[minstret] = &this_class::read_instret; + csr_wr_cb[minstret] = &this_class::write_instret; + if(traits::XLEN == 32) + csr_rd_cb[minstreth] = &this_class::read_instret; + if(traits::XLEN == 32) + csr_wr_cb[minstreth] = &this_class::write_instret; + csr_rd_cb[mstatus] = &this_class::read_status; + csr_wr_cb[mstatus] = &this_class::write_status; + csr_rd_cb[mcause] = &this_class::read_cause; + csr_wr_cb[mcause] = &this_class::write_cause; + csr_rd_cb[mtvec] = &this_class::read_tvec; + csr_wr_cb[mepc] = &this_class::write_epc; + csr_rd_cb[mip] = &this_class::read_ip; + csr_wr_cb[mip] = &this_class::write_null; + csr_rd_cb[mie] = &this_class::read_ie; + csr_wr_cb[mie] = &this_class::write_ie; + csr_rd_cb[mhartid] = &this_class::read_hartid; + csr_rd_cb[mcounteren] = &this_class::read_null; + csr_wr_cb[mcounteren] = &this_class::write_null; + csr_wr_cb[misa] = &this_class::write_null; + csr_wr_cb[mvendorid] = &this_class::write_null; + csr_wr_cb[marchid] = &this_class::write_null; + csr_wr_cb[mimpid] = &this_class::write_null; + + if(FEAT & FEAT_PMP) { + for(size_t i = pmpaddr0; i <= pmpaddr15; ++i) { + csr_rd_cb[i] = &this_class::read_csr_reg; + csr_wr_cb[i] = &this_class::write_csr_reg; + } + for(size_t i = pmpcfg0; i < pmpcfg0 + 16 / sizeof(reg_t); ++i) { + csr_rd_cb[i] = &this_class::read_csr_reg; + csr_wr_cb[i] = &this_class::write_pmpcfg_reg; + } + } + if(FEAT & FEAT_EXT_N) { + csr_rd_cb[mideleg] = &this_class::read_csr_reg; + csr_wr_cb[mideleg] = &this_class::write_ideleg; + csr_rd_cb[medeleg] = &this_class::read_csr_reg; + csr_wr_cb[medeleg] = &this_class::write_edeleg; + csr_rd_cb[uie] = &this_class::read_ie; + csr_wr_cb[uie] = &this_class::write_ie; + csr_rd_cb[uip] = &this_class::read_ip; + csr_wr_cb[uip] = &this_class::write_null; + csr_wr_cb[uepc] = &this_class::write_epc; + csr_rd_cb[ustatus] = &this_class::read_status; + csr_wr_cb[ustatus] = &this_class::write_status; + csr_rd_cb[ucause] = &this_class::read_cause; + csr_wr_cb[ucause] = &this_class::write_cause; + csr_rd_cb[utvec] = &this_class::read_tvec; + } + if(FEAT & FEAT_CLIC) { + csr_rd_cb[mtvt] = &this_class::read_csr_reg; + csr_wr_cb[mtvt] = &this_class::write_xtvt; + // csr_rd_cb[mxnti] = &this_class::read_csr_reg; + // csr_wr_cb[mxnti] = &this_class::write_csr_reg; + csr_rd_cb[mintstatus] = &this_class::read_intstatus; + csr_wr_cb[mintstatus] = &this_class::write_null; + // csr_rd_cb[mscratchcsw] = &this_class::read_csr_reg; + // csr_wr_cb[mscratchcsw] = &this_class::write_csr_reg; + // csr_rd_cb[mscratchcswl] = &this_class::read_csr_reg; + // csr_wr_cb[mscratchcswl] = &this_class::write_csr_reg; + csr_rd_cb[mintthresh] = &this_class::read_csr_reg; + csr_wr_cb[mintthresh] = &this_class::write_intthresh; + if(FEAT & FEAT_EXT_N) { + csr_rd_cb[utvt] = &this_class::read_csr_reg; + csr_wr_cb[utvt] = &this_class::write_xtvt; + csr_rd_cb[uintstatus] = &this_class::read_intstatus; + csr_wr_cb[uintstatus] = &this_class::write_null; + csr_rd_cb[uintthresh] = &this_class::read_csr_reg; + csr_wr_cb[uintthresh] = &this_class::write_intthresh; + } + clic_int_reg.resize(cfg.clic_num_irq, clic_int_reg_t{.raw = 0}); + clic_cfg_reg = 0x30; + clic_mact_lvl = clic_mprev_lvl = (1 << (cfg.clic_int_ctl_bits)) - 1; + clic_uact_lvl = clic_uprev_lvl = (1 << (cfg.clic_int_ctl_bits)) - 1; + csr[mintthresh] = (1 << (cfg.clic_int_ctl_bits)) - 1; + csr[uintthresh] = (1 << (cfg.clic_int_ctl_bits)) - 1; + insert_mem_range( + cfg.clic_base, 0x5000UL, + [this](phys_addr_t addr, unsigned length, uint8_t* const data) { return read_clic(addr.val, length, data); }, + [this](phys_addr_t addr, unsigned length, uint8_t const* const data) { return write_clic(addr.val, length, data); }); + } + if(FEAT & FEAT_TCM) { + tcm.resize(cfg.tcm_size); + std::function read_clic_cb = [this](phys_addr_t addr, unsigned length, uint8_t* const data) { + auto offset = addr.val - this->cfg.tcm_base; + std::copy(tcm.data() + offset, tcm.data() + offset + length, data); + return iss::Ok; + }; + std::function write_clic_cb = [this](phys_addr_t addr, unsigned length, uint8_t const* const data) { + auto offset = addr.val - this->cfg.tcm_base; + std::copy(data, data + length, tcm.data() + offset); + return iss::Ok; + }; + insert_mem_range(cfg.tcm_base, cfg.tcm_size, read_clic_cb, write_clic_cb); + } + if(FEAT & FEAT_DEBUG) { + csr_wr_cb[dscratch0] = &this_class::write_dcsr_reg; + csr_rd_cb[dscratch0] = &this_class::read_dcsr_reg; + csr_wr_cb[dscratch1] = &this_class::write_dcsr_reg; + csr_rd_cb[dscratch1] = &this_class::read_dcsr_reg; + csr_wr_cb[dpc] = &this_class::write_dpc_reg; + csr_rd_cb[dpc] = &this_class::read_dpc_reg; + csr_wr_cb[dcsr] = &this_class::write_dcsr_dcsr; + csr_rd_cb[dcsr] = &this_class::read_dcsr_reg; + } + hart_mem_rd_delegate = [this](phys_addr_t a, unsigned l, uint8_t* const d) -> iss::status { return this->read_mem(a, l, d); }; + hart_mem_wr_delegate = [this](phys_addr_t a, unsigned l, uint8_t const* const d) -> iss::status { return this->write_mem(a, l, d); }; +} + +template std::pair riscv_hart_mu_p::load_file(std::string name, int type) { + FILE* fp = fopen(name.c_str(), "r"); + if(fp) { + std::array buf; + auto n = fread(buf.data(), 1, 4, fp); + fclose(fp); + if(n != 4) + throw std::runtime_error("input file has insufficient size"); + buf[4] = 0; + if(strcmp(buf.data() + 1, "ELF") == 0) { + // Create elfio reader + ELFIO::elfio reader; + // Load ELF data + if(!reader.load(name)) + throw std::runtime_error("could not process elf file"); + // check elf properties + if(reader.get_class() != ELFCLASS32) + if(sizeof(reg_t) == 4) + throw std::runtime_error("wrong elf class in file"); + if(reader.get_type() != ET_EXEC) + throw std::runtime_error("wrong elf type in file"); + if(reader.get_machine() != EM_RISCV) + throw std::runtime_error("wrong elf machine in file"); + auto entry = reader.get_entry(); + for(const auto pseg : reader.segments) { + const auto fsize = pseg->get_file_size(); // 0x42c/0x0 + const auto seg_data = pseg->get_data(); + if(fsize > 0) { + auto res = this->write(iss::address_type::PHYSICAL, iss::access_type::DEBUG_WRITE, traits::MEM, + pseg->get_physical_address(), fsize, reinterpret_cast(seg_data)); + if(res != iss::Ok) + LOG(ERR) << "problem writing " << fsize << "bytes to 0x" << std::hex << pseg->get_physical_address(); + } + } + for(const auto sec : reader.sections) { + if(sec->get_name() == ".symtab") { + if(SHT_SYMTAB == sec->get_type() || SHT_DYNSYM == sec->get_type()) { + ELFIO::symbol_section_accessor symbols(reader, sec); + auto sym_no = symbols.get_symbols_num(); + std::string name; + ELFIO::Elf64_Addr value = 0; + ELFIO::Elf_Xword size = 0; + unsigned char bind = 0; + unsigned char type = 0; + ELFIO::Elf_Half section = 0; + unsigned char other = 0; + for(auto i = 0U; i < sym_no; ++i) { + symbols.get_symbol(i, name, value, size, bind, type, section, other); + if(name == "tohost") { + tohost = value; + } else if(name == "fromhost") { + fromhost = value; + } + } + } + } else if(sec->get_name() == ".tohost") { + tohost = sec->get_address(); + fromhost = tohost + 0x40; + } + } + return std::make_pair(entry, true); + } + throw std::runtime_error(fmt::format("memory load file {} is not a valid elf file", name)); + } + throw std::runtime_error(fmt::format("memory load file not found, check if {} is a valid file", name)); +} + +template +inline void riscv_hart_mu_p::insert_mem_range(uint64_t base, uint64_t size, std::function rd_f, + std::function wr_fn) { + std::tuple entry{base, size}; + auto it = std::upper_bound( + memfn_range.begin(), memfn_range.end(), entry, + [](std::tuple const& a, std::tuple const& b) { return std::get<0>(a) < std::get<0>(b); }); + auto idx = std::distance(memfn_range.begin(), it); + memfn_range.insert(it, entry); + memfn_read.insert(std::begin(memfn_read) + idx, rd_f); + memfn_write.insert(std::begin(memfn_write) + idx, wr_fn); +} + +template inline iss::status riscv_hart_mu_p::write_pmpcfg_reg(unsigned addr, reg_t val) { + csr[addr] = val & 0x9f9f9f9f; + return iss::Ok; +} + +template +bool riscv_hart_mu_p::pmp_check(const access_type type, const uint64_t addr, const unsigned len) { + constexpr auto PMP_SHIFT = 2U; + constexpr auto PMP_R = 0x1U; + constexpr auto PMP_W = 0x2U; + constexpr auto PMP_X = 0x4U; + constexpr auto PMP_A = 0x18U; + constexpr auto PMP_L = 0x80U; + constexpr auto PMP_TOR = 0x1U; + constexpr auto PMP_NA4 = 0x2U; + constexpr auto PMP_NAPOT = 0x3U; + reg_t base = 0; + auto any_active = false; + auto const cfg_reg_size = sizeof(reg_t); + for(size_t i = 0; i < 16; i++) { + reg_t tor = csr[pmpaddr0 + i] << PMP_SHIFT; + uint8_t cfg = csr[pmpcfg0 + (i / cfg_reg_size)] >> (i % cfg_reg_size); + if(cfg & PMP_A) { + any_active = true; + auto pmp_a = (cfg & PMP_A) >> 3; + auto is_tor = pmp_a == PMP_TOR; + auto is_na4 = pmp_a == PMP_NA4; + + reg_t mask = (csr[pmpaddr0 + i] << 1) | (!is_na4); + mask = ~(mask & ~(mask + 1)) << PMP_SHIFT; + + // Check each 4-byte sector of the access + auto any_match = false; + auto all_match = true; + for(reg_t offset = 0; offset < len; offset += 1 << PMP_SHIFT) { + reg_t cur_addr = addr + offset; + auto napot_match = ((cur_addr ^ tor) & mask) == 0; + auto tor_match = base <= (cur_addr + len - 1) && cur_addr < tor; + auto match = is_tor ? tor_match : napot_match; + any_match |= match; + all_match &= match; + } + if(any_match) { + // If the PMP matches only a strict subset of the access, fail it + if(!all_match) + return false; + return (this->reg.PRIV == PRIV_M && !(cfg & PMP_L)) || (type == access_type::READ && (cfg & PMP_R)) || + (type == access_type::WRITE && (cfg & PMP_W)) || (type == access_type::FETCH && (cfg & PMP_X)); + } + } + base = tor; + } + // constexpr auto pmp_num_regs = 16; + // reg_t tor_base = 0; + // auto any_active = false; + // auto lower_addr = addr >>2; + // auto upper_addr = (addr+len-1)>>2; + // for (size_t i = 0; i < pmp_num_regs; i++) { + // uint8_t cfg = csr[pmpcfg0+(i/4)]>>(i%4); + // uint8_t cfg_next = i==(pmp_num_regs-1)? 0 : csr[pmpcfg0+((i+1)/4)]>>((i+1)%4); + // auto pmpaddr = csr[pmpaddr0+i]; + // if (cfg & PMP_A) { + // any_active=true; + // auto is_tor = bit_sub<3, 2>(cfg) == PMP_TOR; + // auto is_napot = bit_sub<4, 1>(cfg) && bit_sub<3, 2>(cfg_next)!= PMP_TOR; + // if(is_napot) { + // reg_t mask = bit_sub<3, 1>(cfg)?~( pmpaddr & ~(pmpaddr + 1)): 0x3fffffff; + // auto mpmpaddr = pmpaddr & mask; + // if((lower_addr&mask) == mpmpaddr && (upper_addr&mask)==mpmpaddr) + // return (this->reg.PRIV == PRIV_M && !(cfg & PMP_L)) || + // (type == access_type::READ && (cfg & PMP_R)) || + // (type == access_type::WRITE && (cfg & PMP_W)) || + // (type == access_type::FETCH && (cfg & PMP_X)); + // } else if(is_tor) { + // if(lower_addr>=tor_base && upper_addr<=pmpaddr) + // return (this->reg.PRIV == PRIV_M && !(cfg & PMP_L)) || + // (type == access_type::READ && (cfg & PMP_R)) || + // (type == access_type::WRITE && (cfg & PMP_W)) || + // (type == access_type::FETCH && (cfg & PMP_X)); + // } + // } + // tor_base = pmpaddr; + // } + return !any_active || this->reg.PRIV == PRIV_M; +} + +template +iss::status riscv_hart_mu_p::read(const address_type type, const access_type access, const uint32_t space, const uint64_t addr, + const unsigned length, uint8_t* const data) { +#ifndef NDEBUG + if(access && iss::access_type::DEBUG) { + LOG(TRACEALL) << "debug read of " << length << " bytes @addr 0x" << std::hex << addr; + } else if(is_fetch(access)) { + LOG(TRACEALL) << "fetch of " << length << " bytes @addr 0x" << std::hex << addr; + } else { + LOG(TRACE) << "read of " << length << " bytes @addr 0x" << std::hex << addr; + } +#endif + try { + switch(space) { + case traits::MEM: { + if(FEAT & FEAT_PMP) { + if(!pmp_check(access, addr, length) && !is_debug(access)) { + fault_data = addr; + if(is_debug(access)) + throw trap_access(0, addr); + this->reg.trap_state = (1UL << 31) | ((access == access_type::FETCH ? 1 : 5) << 16); // issue trap 1 + return iss::Err; + } + } + auto alignment = is_fetch(access) ? (has_compressed() ? 2 : 4) : length; + if(unlikely(is_fetch(access) && (addr & (alignment - 1)))) { + fault_data = addr; + if(is_debug(access)) + throw trap_access(0, addr); + this->reg.trap_state = (1UL << 31); // issue trap 0 + return iss::Err; + } + try { + if(!is_debug(access) && (addr & (alignment - 1))) { + this->reg.trap_state = (1UL << 31) | 4 << 16; + fault_data = addr; + return iss::Err; + } + phys_addr_t phys_addr{access, space, addr}; + auto res = iss::Err; + if(!is_fetch(access) && memfn_range.size()) { + auto it = + std::find_if(std::begin(memfn_range), std::end(memfn_range), [phys_addr](std::tuple const& a) { + return std::get<0>(a) <= phys_addr.val && (std::get<0>(a) + std::get<1>(a)) > phys_addr.val; + }); + if(it != std::end(memfn_range)) { + auto idx = std::distance(std::begin(memfn_range), it); + res = memfn_read[idx](phys_addr, length, data); + } else + res = hart_mem_rd_delegate(phys_addr, length, data); + } else { + res = hart_mem_rd_delegate(phys_addr, length, data); + } + if(unlikely(res != iss::Ok && (access & access_type::DEBUG) == 0)) { + this->reg.trap_state = (1UL << 31) | (5 << 16); // issue trap 5 (load access fault + fault_data = addr; + } + return res; + } catch(trap_access& ta) { + this->reg.trap_state = (1UL << 31) | ta.id; + fault_data = ta.addr; + return iss::Err; + } + } break; + case traits::CSR: { + if(length != sizeof(reg_t)) + return iss::Err; + return read_csr(addr, *reinterpret_cast(data)); + } break; + case traits::FENCE: { + if((addr + length) > mem.size()) + return iss::Err; + return iss::Ok; + } break; + case traits::RES: { + auto it = atomic_reservation.find(addr); + if(it != atomic_reservation.end() && it->second != 0) { + memset(data, 0xff, length); + atomic_reservation.erase(addr); + } else + memset(data, 0, length); + } break; + default: + return iss::Err; // assert("Not supported"); + } + return iss::Ok; + } catch(trap_access& ta) { + this->reg.trap_state = (1UL << 31) | ta.id; + fault_data = ta.addr; + return iss::Err; + } +} + +template +iss::status riscv_hart_mu_p::write(const address_type type, const access_type access, const uint32_t space, const uint64_t addr, + const unsigned length, const uint8_t* const data) { +#ifndef NDEBUG + const char* prefix = (access && iss::access_type::DEBUG) ? "debug " : ""; + switch(length) { + case 8: + LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint64_t*)&data[0] << std::dec << ") @addr 0x" + << std::hex << addr; + break; + case 4: + LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint32_t*)&data[0] << std::dec << ") @addr 0x" + << std::hex << addr; + break; + case 2: + LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint16_t*)&data[0] << std::dec << ") @addr 0x" + << std::hex << addr; + break; + case 1: + LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << (uint16_t)data[0] << std::dec << ") @addr 0x" + << std::hex << addr; + break; + default: + LOG(TRACE) << prefix << "write of " << length << " bytes @addr " << addr; + } +#endif + try { + switch(space) { + case traits::MEM: { + if(FEAT & FEAT_PMP) { + if(!pmp_check(access, addr, length) && (access & access_type::DEBUG) != access_type::DEBUG) { + fault_data = addr; + if(access && iss::access_type::DEBUG) + throw trap_access(0, addr); + this->reg.trap_state = (1UL << 31) | (7 << 16); // issue trap 1 + return iss::Err; + } + } + if(unlikely(is_fetch(access) && (addr & 0x1) == 1)) { + fault_data = addr; + if(access && iss::access_type::DEBUG) + throw trap_access(0, addr); + this->reg.trap_state = (1UL << 31); // issue trap 0 + return iss::Err; + } + try { + if(length > 1 && (addr & (length - 1)) && (access & access_type::DEBUG) != access_type::DEBUG) { + this->reg.trap_state = (1UL << 31) | 6 << 16; + fault_data = addr; + return iss::Err; + } + phys_addr_t phys_addr{access, space, addr}; + auto res = iss::Err; + if(!is_fetch(access) && memfn_range.size()) { + auto it = + std::find_if(std::begin(memfn_range), std::end(memfn_range), [phys_addr](std::tuple const& a) { + return std::get<0>(a) <= phys_addr.val && (std::get<0>(a) + std::get<1>(a)) > phys_addr.val; + }); + if(it != std::end(memfn_range)) { + auto idx = std::distance(std::begin(memfn_range), it); + res = memfn_write[idx](phys_addr, length, data); + } else + res = hart_mem_wr_delegate(phys_addr, length, data); + } else { + res = hart_mem_wr_delegate(phys_addr, length, data); + } + if(unlikely(res != iss::Ok && (access & access_type::DEBUG) == 0)) { + this->reg.trap_state = (1UL << 31) | (7UL << 16); // issue trap 7 (Store/AMO access fault) + fault_data = addr; + } + return res; + } catch(trap_access& ta) { + this->reg.trap_state = (1UL << 31) | ta.id; + fault_data = ta.addr; + return iss::Err; + } + + if((addr + length) > mem.size()) + return iss::Err; + switch(addr) { + case 0x10013000: // UART0 base, TXFIFO reg + case 0x10023000: // UART1 base, TXFIFO reg + uart_buf << (char)data[0]; + if(((char)data[0]) == '\n' || data[0] == 0) { + // LOG(INFO)<<"UART"<<((addr>>16)&0x3)<<" send + // '"<::CSR: { + if(length != sizeof(reg_t)) + return iss::Err; + return write_csr(addr, *reinterpret_cast(data)); + } break; + case traits::FENCE: { + if((addr + length) > mem.size()) + return iss::Err; + switch(addr) { + case 2: + case 3: { + ptw.clear(); + auto tvm = state.mstatus.TVM; + return iss::Ok; + } + } + } break; + case traits::RES: { + atomic_reservation[addr] = data[0]; + } break; + default: + return iss::Err; + } + return iss::Ok; + } catch(trap_access& ta) { + this->reg.trap_state = (1UL << 31) | ta.id; + fault_data = ta.addr; + return iss::Err; + } +} + +template iss::status riscv_hart_mu_p::read_csr(unsigned addr, reg_t& val) { + if(addr >= csr.size()) + return iss::Err; + auto req_priv_lvl = (addr >> 8) & 0x3; + if(this->reg.PRIV < req_priv_lvl) // not having required privileges + throw illegal_instruction_fault(this->fault_data); + auto it = csr_rd_cb.find(addr); + if(it == csr_rd_cb.end() || !it->second) // non existent register + throw illegal_instruction_fault(this->fault_data); + return (this->*(it->second))(addr, val); +} + +template iss::status riscv_hart_mu_p::write_csr(unsigned addr, reg_t val) { + if(addr >= csr.size()) + return iss::Err; + auto req_priv_lvl = (addr >> 8) & 0x3; + if(this->reg.PRIV < req_priv_lvl) // not having required privileges + throw illegal_instruction_fault(this->fault_data); + if((addr & 0xc00) == 0xc00) // writing to read-only region + throw illegal_instruction_fault(this->fault_data); + auto it = csr_wr_cb.find(addr); + if(it == csr_wr_cb.end() || !it->second) // non existent register + throw illegal_instruction_fault(this->fault_data); + return (this->*(it->second))(addr, val); +} + +template iss::status riscv_hart_mu_p::read_csr_reg(unsigned addr, reg_t& val) { + val = csr[addr]; + return iss::Ok; +} + +template iss::status riscv_hart_mu_p::read_null(unsigned addr, reg_t& val) { + val = 0; + return iss::Ok; +} + +template iss::status riscv_hart_mu_p::write_csr_reg(unsigned addr, reg_t val) { + csr[addr] = val; + return iss::Ok; +} + +template iss::status riscv_hart_mu_p::read_cycle(unsigned addr, reg_t& val) { + auto cycle_val = this->reg.icount + cycle_offset; + if(addr == mcycle) { + val = static_cast(cycle_val); + } else if(addr == mcycleh) { + val = static_cast(cycle_val >> 32); + } + return iss::Ok; +} + +template iss::status riscv_hart_mu_p::write_cycle(unsigned addr, reg_t val) { + if(sizeof(typename traits::reg_t) != 4) { + mcycle_csr = static_cast(val); + } else { + if(addr == mcycle) { + mcycle_csr = (mcycle_csr & 0xffffffff00000000) + val; + } else { + mcycle_csr = (static_cast(val) << 32) + (mcycle_csr & 0xffffffff); + } + } + cycle_offset = mcycle_csr - this->reg.icount; // TODO: relying on wrap-around + return iss::Ok; +} + +template iss::status riscv_hart_mu_p::read_instret(unsigned addr, reg_t& val) { + if((addr & 0xff) == (minstret & 0xff)) { + val = static_cast(this->reg.instret); + } else if((addr & 0xff) == (minstreth & 0xff)) { + val = static_cast(this->reg.instret >> 32); + } + return iss::Ok; +} + +template iss::status riscv_hart_mu_p::write_instret(unsigned addr, reg_t val) { + if(sizeof(typename traits::reg_t) != 4) { + this->reg.instret = static_cast(val); + } else { + if((addr & 0xff) == (minstret & 0xff)) { + this->reg.instret = (this->reg.instret & 0xffffffff00000000) + val; + } else { + this->reg.instret = (static_cast(val) << 32) + (this->reg.instret & 0xffffffff); + } + } + this->reg.instret--; + return iss::Ok; +} + +template iss::status riscv_hart_mu_p::read_time(unsigned addr, reg_t& val) { + uint64_t time_val = this->reg.icount / (100000000 / 32768 - 1); //-> ~3052; + if(addr == time) { + val = static_cast(time_val); + } else if(addr == timeh) { + if(sizeof(typename traits::reg_t) != 4) + return iss::Err; + val = static_cast(time_val >> 32); + } + return iss::Ok; +} + +template iss::status riscv_hart_mu_p::read_tvec(unsigned addr, reg_t& val) { + val = FEAT & features_e::FEAT_CLIC ? csr[addr] : csr[addr] & ~2; + return iss::Ok; +} +template iss::status riscv_hart_mu_p::read_status(unsigned addr, reg_t& val) { + val = state.mstatus & hart_state_type::get_mask((addr >> 8) & 0x3); + return iss::Ok; +} + +template iss::status riscv_hart_mu_p::write_status(unsigned addr, reg_t val) { + state.write_mstatus(val, (addr >> 8) & 0x3); + check_interrupt(); + return iss::Ok; +} + +template iss::status riscv_hart_mu_p::read_cause(unsigned addr, reg_t& val) { + if((FEAT & features_e::FEAT_CLIC) && (csr[mtvec] & 0x3) == 3) { + val = csr[addr] & ((1UL << (traits::XLEN - 1)) | (mcause_max_irq - 1) | (0xfUL << 16)); + auto mode = (addr >> 8) & 0x3; + switch(mode) { + case 0: + val |= clic_uprev_lvl << 16; + val |= state.mstatus.UPIE << 27; + break; + default: + val |= clic_mprev_lvl << 16; + val |= state.mstatus.MPIE << 27; + val |= state.mstatus.MPP << 28; + break; + } + } else + val = csr[addr] & ((1UL << (traits::XLEN - 1)) | (mcause_max_irq - 1)); + return iss::Ok; +} + +template iss::status riscv_hart_mu_p::write_cause(unsigned addr, reg_t val) { + if((FEAT & features_e::FEAT_CLIC) && (csr[mtvec] & 0x3) == 3) { + auto mask = ((1UL << (traits::XLEN - 1)) | (mcause_max_irq - 1) | (0xfUL << 16)); + csr[addr] = (val & mask) | (csr[addr] & ~mask); + auto mode = (addr >> 8) & 0x3; + switch(mode) { + case 0: + clic_uprev_lvl = ((val >> 16) & 0xff) | (1 << (8 - cfg.clic_int_ctl_bits)) - 1; + state.mstatus.UPIE = (val >> 27) & 0x1; + break; + default: + clic_mprev_lvl = ((val >> 16) & 0xff) | (1 << (8 - cfg.clic_int_ctl_bits)) - 1; + state.mstatus.MPIE = (val >> 27) & 0x1; + state.mstatus.MPP = (val >> 28) & 0x3; + break; + } + } else { + auto mask = ((1UL << (traits::XLEN - 1)) | (mcause_max_irq - 1)); + csr[addr] = (val & mask) | (csr[addr] & ~mask); + } + return iss::Ok; +} + +template iss::status riscv_hart_mu_p::read_hartid(unsigned addr, reg_t& val) { + val = mhartid_reg; + return iss::Ok; +} + +template iss::status riscv_hart_mu_p::read_ie(unsigned addr, reg_t& val) { + auto mask = get_irq_mask((addr >> 8) & 0x3); + val = csr[mie] & mask; + if(this->reg.PRIV != 3) + val &= csr[mideleg]; + return iss::Ok; +} + +template iss::status riscv_hart_mu_p::write_ie(unsigned addr, reg_t val) { + auto mask = get_irq_mask((addr >> 8) & 0x3); + csr[mie] = (csr[mie] & ~mask) | (val & mask); + check_interrupt(); + return iss::Ok; +} + +template iss::status riscv_hart_mu_p::read_ip(unsigned addr, reg_t& val) { + auto mask = get_irq_mask((addr >> 8) & 0x3); + val = csr[mip] & mask; + if(this->reg.PRIV != 3) + val &= csr[mideleg]; + return iss::Ok; +} + +template iss::status riscv_hart_mu_p::write_ideleg(unsigned addr, reg_t val) { + auto mask = 0b000100010001; // only U mode supported + csr[mideleg] = (csr[mideleg] & ~mask) | (val & mask); + return iss::Ok; +} + +template iss::status riscv_hart_mu_p::write_edeleg(unsigned addr, reg_t val) { + auto mask = 0b1011001111110111; // bit 14/10 (reserved), bit 11 (Env call), and 3 (break) are hardwired to 0 + csr[medeleg] = (csr[medeleg] & ~mask) | (val & mask); + return iss::Ok; +} + +template iss::status riscv_hart_mu_p::write_epc(unsigned addr, reg_t val) { + csr[addr] = val & get_pc_mask(); + return iss::Ok; +} + +template iss::status riscv_hart_mu_p::write_dcsr_dcsr(unsigned addr, reg_t val) { + if(!debug_mode_active()) + throw illegal_instruction_fault(this->fault_data); + // +-------------- ebreakm + // | +---------- stepi + // | | +++----- cause + // | | ||| +- step + csr[addr] = val & 0b1000100111000100U; + return iss::Ok; +} + +template iss::status riscv_hart_mu_p::read_dcsr_reg(unsigned addr, reg_t& val) { + if(!debug_mode_active()) + throw illegal_instruction_fault(this->fault_data); + val = csr[addr]; + return iss::Ok; +} + +template iss::status riscv_hart_mu_p::write_dcsr_reg(unsigned addr, reg_t val) { + if(!debug_mode_active()) + throw illegal_instruction_fault(this->fault_data); + csr[addr] = val; + return iss::Ok; +} + +template iss::status riscv_hart_mu_p::read_dpc_reg(unsigned addr, reg_t& val) { + if(!debug_mode_active()) + throw illegal_instruction_fault(this->fault_data); + val = this->reg.DPC; + return iss::Ok; +} + +template iss::status riscv_hart_mu_p::write_dpc_reg(unsigned addr, reg_t val) { + if(!debug_mode_active()) + throw illegal_instruction_fault(this->fault_data); + this->reg.DPC = val; + return iss::Ok; +} + +template iss::status riscv_hart_mu_p::read_intstatus(unsigned addr, reg_t& val) { + auto mode = (addr >> 8) & 0x3; + val = clic_uact_lvl & 0xff; + if(mode == 0x3) + val += (clic_mact_lvl & 0xff) << 24; + return iss::Ok; +} + +template iss::status riscv_hart_mu_p::write_intthresh(unsigned addr, reg_t val) { + csr[addr] = (val & 0xff) | (1 << (cfg.clic_int_ctl_bits)) - 1; + return iss::Ok; +} + +template iss::status riscv_hart_mu_p::write_xtvt(unsigned addr, reg_t val) { + csr[addr] = val & ~0x3fULL; + return iss::Ok; +} + +template +iss::status riscv_hart_mu_p::read_mem(phys_addr_t paddr, unsigned length, uint8_t* const data) { + switch(paddr.val) { + default: { + for(auto offs = 0U; offs < length; ++offs) { + *(data + offs) = mem[(paddr.val + offs) % mem.size()]; + } + } + } + return iss::Ok; +} + +template +iss::status riscv_hart_mu_p::write_mem(phys_addr_t paddr, unsigned length, const uint8_t* const data) { + switch(paddr.val) { + case 0xFFFF0000: // UART0 base, TXFIFO reg + if(((char)data[0]) == '\n' || data[0] == 0) { + LOG(INFO) << "UART" << ((paddr.val >> 12) & 0x3) << " send '" << uart_buf.str() << "'"; + uart_buf.str(""); + } else if(((char)data[0]) != '\r') + uart_buf << (char)data[0]; + break; + default: { + mem_type::page_type& p = mem(paddr.val / mem.page_size); + std::copy(data, data + length, p.data() + (paddr.val & mem.page_addr_mask)); + // tohost handling in case of riscv-test + if(paddr.access && iss::access_type::FUNC) { + auto tohost_upper = + (traits::XLEN == 32 && paddr.val == (tohost + 4)) || (traits::XLEN == 64 && paddr.val == tohost); + auto tohost_lower = (traits::XLEN == 32 && paddr.val == tohost) || (traits::XLEN == 64 && paddr.val == tohost); + if(tohost_lower || tohost_upper) { + uint64_t hostvar = *reinterpret_cast(p.data() + (tohost & mem.page_addr_mask)); + if(tohost_upper || (tohost_lower && to_host_wr_cnt > 0)) { + switch(hostvar >> 48) { + case 0: + if(hostvar != 0x1) { + LOG(FATAL) << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar + << "), stopping simulation"; + } else { + LOG(INFO) << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar + << "), stopping simulation"; + } + this->reg.trap_state = std::numeric_limits::max(); + this->interrupt_sim = hostvar; + break; + // throw(iss::simulation_stopped(hostvar)); + case 0x0101: { + char c = static_cast(hostvar & 0xff); + if(c == '\n' || c == 0) { + LOG(INFO) << "tohost send '" << uart_buf.str() << "'"; + uart_buf.str(""); + } else + uart_buf << c; + to_host_wr_cnt = 0; + } break; + default: + break; + } + } else if(tohost_lower) + to_host_wr_cnt++; + } else if((traits::XLEN == 32 && paddr.val == fromhost + 4) || (traits::XLEN == 64 && paddr.val == fromhost)) { + uint64_t fhostvar = *reinterpret_cast(p.data() + (fromhost & mem.page_addr_mask)); + *reinterpret_cast(p.data() + (tohost & mem.page_addr_mask)) = fhostvar; + } + } + } + } + return iss::Ok; +} + +template +iss::status riscv_hart_mu_p::read_clic(uint64_t addr, unsigned length, uint8_t* const data) { + if(addr == cfg.clic_base) { // cliccfg + *data = clic_cfg_reg; + for(auto i = 1; i < length; ++i) + *(data + i) = 0; + } else if(addr >= (cfg.clic_base + 0x40) && (addr + length) <= (cfg.clic_base + 0x40 + cfg.clic_num_trigger * 4)) { // clicinttrig + auto offset = ((addr & 0x7fff) - 0x40) / 4; + read_reg_uint32(addr, clic_inttrig_reg[offset], data, length); + } else if(addr >= (cfg.clic_base + 0x1000) && + (addr + length) <= (cfg.clic_base + 0x1000 + cfg.clic_num_irq * 4)) { // clicintip/clicintie/clicintattr/clicintctl + auto offset = ((addr & 0x7fff) - 0x1000) / 4; + read_reg_uint32(addr, clic_int_reg[offset].raw, data, length); + } else { + for(auto i = 0U; i < length; ++i) + *(data + i) = 0; + } + return iss::Ok; +} + +template +iss::status riscv_hart_mu_p::write_clic(uint64_t addr, unsigned length, const uint8_t* const data) { + if(addr == cfg.clic_base) { // cliccfg + clic_cfg_reg = (clic_cfg_reg & ~0x1e) | (*data & 0x1e); + } else if(addr >= (cfg.clic_base + 0x40) && (addr + length) <= (cfg.clic_base + 0x40 + cfg.clic_num_trigger * 4)) { // clicinttrig + auto offset = ((addr & 0x7fff) - 0x40) / 4; + write_reg_uint32(addr, clic_inttrig_reg[offset], data, length); + } else if(addr >= (cfg.clic_base + 0x1000) && + (addr + length) <= (cfg.clic_base + 0x1000 + cfg.clic_num_irq * 4)) { // clicintip/clicintie/clicintattr/clicintctl + auto offset = ((addr & 0x7fff) - 0x1000) / 4; + write_reg_uint32(addr, clic_int_reg[offset].raw, data, length); + clic_int_reg[offset].raw &= 0xf0c70101; // clicIntCtlBits->0xf0, clicintattr->0xc7, clicintie->0x1, clicintip->0x1 + } + return iss::Ok; +} + +template inline void riscv_hart_mu_p::reset(uint64_t address) { + BASE::reset(address); + state.mstatus = hart_state_type::mstatus_reset_val; +} + +template void riscv_hart_mu_p::check_interrupt() { + // TODO: Implement CLIC functionality + auto ideleg = csr[mideleg]; + // Multiple simultaneous interrupts and traps at the same privilege level are + // handled in the following decreasing priority order: + // external interrupts, software interrupts, timer interrupts, then finally + // any synchronous traps. + auto ena_irq = csr[mip] & csr[mie]; + + bool mstatus_mie = state.mstatus.MIE; + auto m_enabled = this->reg.PRIV < PRIV_M || mstatus_mie; + auto enabled_interrupts = m_enabled ? ena_irq & ~ideleg : 0; + + if(enabled_interrupts != 0) { + int res = 0; + while((enabled_interrupts & 1) == 0) { + enabled_interrupts >>= 1; + res++; + } + this->reg.pending_trap = res << 16 | 1; // 0x80 << 24 | (cause << 16) | trap_id + } +} + +template uint64_t riscv_hart_mu_p::enter_trap(uint64_t flags, uint64_t addr, uint64_t instr) { + // flags are ACTIVE[31:31], CAUSE[30:16], TRAPID[15:0] + // calculate and write mcause val + if(flags == std::numeric_limits::max()) + flags = this->reg.trap_state; + auto trap_id = bit_sub<0, 16>(flags); + auto cause = bit_sub<16, 15>(flags); + if(trap_id == 0 && cause == 11) + cause = 0x8 + this->reg.PRIV; // adjust environment call cause + // calculate effective privilege level + unsigned new_priv = PRIV_M; + if(trap_id == 0) { // exception + if(this->reg.PRIV != PRIV_M && ((csr[medeleg] >> cause) & 0x1) != 0) + new_priv = PRIV_U; + // store ret addr in xepc register + csr[uepc | (new_priv << 8)] = static_cast(addr); // store actual address instruction of exception + /* + * write mtval if new_priv=M_MODE, spec says: + * When a hardware breakpoint is triggered, or an instruction-fetch, load, + * or store address-misaligned, + * access, or page-fault exception occurs, mtval is written with the + * faulting effective address. + */ + switch(cause) { + case 0: + csr[utval | (new_priv << 8)] = static_cast(addr); + break; + case 2: + csr[utval | (new_priv << 8)] = (!has_compressed() || (instr & 0x3) == 3) ? instr : instr & 0xffff; + break; + case 3: + if((FEAT & FEAT_DEBUG) && (csr[dcsr] & 0x8000)) { + this->reg.DPC = addr; + csr[dcsr] = (csr[dcsr] & ~0x1c3) | (1 << 6) | PRIV_M; // FIXME: cause should not be 4 (stepi) + new_priv = this->reg.PRIV | PRIV_D; + } else { + csr[utval | (new_priv << 8)] = addr; + } + break; + case 4: + case 6: + case 7: + csr[utval | (new_priv << 8)] = fault_data; + break; + default: + csr[utval | (new_priv << 8)] = 0; + } + fault_data = 0; + } else { + if(this->reg.PRIV != PRIV_M && ((csr[mideleg] >> cause) & 0x1) != 0) + new_priv = PRIV_U; + csr[uepc | (new_priv << 8)] = this->reg.NEXT_PC; // store next address if interrupt + this->reg.pending_trap = 0; + } + size_t adr = ucause | (new_priv << 8); + csr[adr] = (trap_id << (traits::XLEN - 1)) + cause; + // update mstatus + // xPP field of mstatus is written with the active privilege mode at the time + // of the trap; the x PIE field of mstatus + // is written with the value of the active interrupt-enable bit at the time of + // the trap; and the x IE field of mstatus + // is cleared + // store the actual privilege level in yPP and store interrupt enable flags + switch(new_priv) { + case PRIV_M: + state.mstatus.MPP = this->reg.PRIV; + state.mstatus.MPIE = state.mstatus.MIE; + state.mstatus.MIE = false; + break; + case PRIV_U: + state.mstatus.UPIE = state.mstatus.UIE; + state.mstatus.UIE = false; + break; + default: + break; + } + + // get trap vector + auto xtvec = csr[utvec | (new_priv << 8)]; + // calculate addr// set NEXT_PC to trap addressess to jump to based on MODE + // bits in mtvec + if((FEAT & features_e::FEAT_CLIC) && trap_id != 0 && (xtvec & 0x3UL) == 3UL) { + reg_t data; + auto ret = read(address_type::LOGICAL, access_type::READ, 0, csr[mtvt], sizeof(reg_t), reinterpret_cast(&data)); + if(ret == iss::Err) + return this->reg.PC; + this->reg.NEXT_PC = data; + } else { + this->reg.NEXT_PC = xtvec & ~0x3UL; + if((xtvec & 0x1) == 1 && trap_id != 0) + this->reg.NEXT_PC += 4 * cause; + } + std::array buffer; +#if defined(_MSC_VER) + sprintf(buffer.data(), "0x%016llx", addr); +#else + sprintf(buffer.data(), "0x%016lx", addr); +#endif + if((flags & 0xffffffff) != 0xffffffff) + CLOG(INFO, disass) << (trap_id ? "Interrupt" : "Trap") << " with cause '" << (trap_id ? irq_str[cause] : trap_str[cause]) << "' (" + << cause << ")" + << " at address " << buffer.data() << " occurred, changing privilege level from " << lvl[this->reg.PRIV] + << " to " << lvl[new_priv]; + // reset trap state + this->reg.PRIV = new_priv; + this->reg.trap_state = 0; + return this->reg.NEXT_PC; +} + +template uint64_t riscv_hart_mu_p::leave_trap(uint64_t flags) { + auto cur_priv = this->reg.PRIV; + auto inst_priv = (flags & 0x3) ? 3 : 0; + if(inst_priv > cur_priv) { + auto trap_val = 0x80ULL << 24 | (2 << 16); // illegal instruction + this->reg.trap_state = trap_val; + this->reg.NEXT_PC = std::numeric_limits::max(); + } else { + auto status = state.mstatus; + // pop the relevant lower-privilege interrupt enable and privilege mode stack + // clear respective yIE + switch(inst_priv) { + case PRIV_M: + this->reg.PRIV = state.mstatus.MPP; + state.mstatus.MPP = 0; // clear mpp to U mode + state.mstatus.MIE = state.mstatus.MPIE; + state.mstatus.MPIE = 1; + break; + case PRIV_U: + this->reg.PRIV = 0; + state.mstatus.UIE = state.mstatus.UPIE; + state.mstatus.UPIE = 1; + break; + } + // sets the pc to the value stored in the x epc register. + this->reg.NEXT_PC = csr[uepc | inst_priv << 8]; + CLOG(INFO, disass) << "Executing xRET , changing privilege level from " << lvl[cur_priv] << " to " << lvl[this->reg.PRIV]; + check_interrupt(); + } + return this->reg.NEXT_PC; +} + +} // namespace arch +} // namespace iss + +#endif /* _RISCV_HART_MU_P_H */ diff --git a/src/iss/tgc_c.cpp b/src/iss/arch/tgc5c.cpp similarity index 76% rename from src/iss/tgc_c.cpp rename to src/iss/arch/tgc5c.cpp index b5e8fed..ae911d7 100644 --- a/src/iss/tgc_c.cpp +++ b/src/iss/arch/tgc5c.cpp @@ -30,29 +30,28 @@ * *******************************************************************************/ +// clang-format off +#include "tgc5c.h" #include "util/ities.h" #include -#include #include #include #include using namespace iss::arch; -constexpr std::array iss::arch::traits::reg_names; -constexpr std::array iss::arch::traits::reg_aliases; -constexpr std::array iss::arch::traits::reg_bit_widths; -constexpr std::array iss::arch::traits::reg_byte_offsets; +constexpr std::array iss::arch::traits::reg_names; +constexpr std::array iss::arch::traits::reg_aliases; +constexpr std::array iss::arch::traits::reg_bit_widths; +constexpr std::array iss::arch::traits::reg_byte_offsets; -tgc_c::tgc_c() { - reg.icount = 0; -} +tgc5c::tgc5c() = default; -tgc_c::~tgc_c() = default; +tgc5c::~tgc5c() = default; -void tgc_c::reset(uint64_t address) { - auto base_ptr = reinterpret_cast::reg_t*>(get_regs_base_ptr()); - for(size_t i=0; i::NUM_REGS; ++i) +void tgc5c::reset(uint64_t address) { + auto base_ptr = reinterpret_cast::reg_t*>(get_regs_base_ptr()); + for(size_t i=0; i::NUM_REGS; ++i) *(base_ptr+i)=0; reg.PC=address; reg.NEXT_PC=reg.PC; @@ -61,11 +60,11 @@ void tgc_c::reset(uint64_t address) { reg.icount=0; } -uint8_t *tgc_c::get_regs_base_ptr() { +uint8_t *tgc5c::get_regs_base_ptr() { return reinterpret_cast(®); } -tgc_c::phys_addr_t tgc_c::virt2phys(const iss::addr_t &pc) { - return phys_addr_t(pc); // change logical address to physical address +tgc5c::phys_addr_t tgc5c::virt2phys(const iss::addr_t &addr) { + return phys_addr_t(addr.access, addr.space, addr.val&traits::addr_mask); } - +// clang-format on diff --git a/incl/iss/arch/tgc_c.h b/src/iss/arch/tgc5c.h similarity index 64% rename from incl/iss/arch/tgc_c.h rename to src/iss/arch/tgc5c.h index 619034d..7285edd 100644 --- a/incl/iss/arch/tgc_c.h +++ b/src/iss/arch/tgc5c.h @@ -30,9 +30,9 @@ * *******************************************************************************/ -#ifndef _TGC_C_H_ -#define _TGC_C_H_ - +#ifndef _TGC5C_H_ +#define _TGC5C_H_ +// clang-format off #include #include #include @@ -41,29 +41,24 @@ namespace iss { namespace arch { -struct tgc_c; +struct tgc5c; -template <> struct traits { +template <> struct traits { - constexpr static char const* const core_type = "TGC_C"; + constexpr static char const* const core_type = "TGC5C"; static constexpr std::array 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", "NEXT_PC", "PRIV", "DPC"}}; + {"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", "next_pc", "priv", "dpc"}}; static constexpr std::array 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", "NEXT_PC", "PRIV", "DPC"}}; + {"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", "next_pc", "priv", "dpc"}}; - enum constants {MISA_VAL=0b01000000000000000001000100000100, MARCHID_VAL=0x80000003, RFS=32, INSTR_ALIGNMENT=2, XLEN=32, CSR_SIZE=4096, fence=0, fencei=1, fencevmal=2, fencevmau=3, MUL_LEN=64}; + enum constants {MISA_VAL=1073746180ULL, MARCHID_VAL=2147483651ULL, CLIC_NUM_IRQ=0ULL, XLEN=32ULL, INSTR_ALIGNMENT=2ULL, RFS=32ULL, fence=0ULL, fencei=1ULL, fencevmal=2ULL, fencevmau=3ULL, CSR_SIZE=4096ULL, MUL_LEN=64ULL}; 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, NEXT_PC, PRIV, DPC, NUM_REGS, - TRAP_STATE=NUM_REGS, - PENDING_TRAP, - ICOUNT, - CYCLE, - INSTRET + 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, NEXT_PC, PRIV, DPC, NUM_REGS, TRAP_STATE=NUM_REGS, PENDING_TRAP, ICOUNT, CYCLE, INSTRET, INSTRUCTION, LAST_BRANCH }; using reg_t = uint32_t; @@ -76,19 +71,19 @@ template <> struct traits { using phys_addr_t = iss::typed_addr_t; - static constexpr std::array 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,8,32,32,32,64,64,64}}; + static constexpr std::array 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,8,32,32,32,64,64,64,32,32}}; - static constexpr std::array 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,137,141,145,149,157,165}}; + static constexpr std::array 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,137,141,145,149,157,165,173,177}}; 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 }; + enum mem_type_e { MEM, FENCE, RES, CSR }; - enum class opcode_e : unsigned short { + enum class opcode_e { LUI = 0, AUIPC = 1, JAL = 2, @@ -129,69 +124,66 @@ template <> struct traits { FENCE = 37, ECALL = 38, EBREAK = 39, - URET = 40, - SRET = 41, - MRET = 42, - WFI = 43, - DRET = 44, - CSRRW = 45, - CSRRS = 46, - CSRRC = 47, - CSRRWI = 48, - CSRRSI = 49, - CSRRCI = 50, - FENCE_I = 51, - MUL = 52, - MULH = 53, - MULHSU = 54, - MULHU = 55, - DIV = 56, - DIVU = 57, - REM = 58, - REMU = 59, - CADDI4SPN = 60, - CLW = 61, - CSW = 62, - CADDI = 63, - CNOP = 64, - CJAL = 65, - CLI = 66, - CLUI = 67, - CADDI16SP = 68, - __reserved_clui = 69, - CSRLI = 70, - CSRAI = 71, - CANDI = 72, - CSUB = 73, - CXOR = 74, - COR = 75, - CAND = 76, - CJ = 77, - CBEQZ = 78, - CBNEZ = 79, - CSLLI = 80, - CLWSP = 81, - CMV = 82, - CJR = 83, - __reserved_cmv = 84, - CADD = 85, - CJALR = 86, - CEBREAK = 87, - CSWSP = 88, - DII = 89, + MRET = 40, + WFI = 41, + CSRRW = 42, + CSRRS = 43, + CSRRC = 44, + CSRRWI = 45, + CSRRSI = 46, + CSRRCI = 47, + FENCE_I = 48, + MUL = 49, + MULH = 50, + MULHSU = 51, + MULHU = 52, + DIV = 53, + DIVU = 54, + REM = 55, + REMU = 56, + C__ADDI4SPN = 57, + C__LW = 58, + C__SW = 59, + C__ADDI = 60, + C__NOP = 61, + C__JAL = 62, + C__LI = 63, + C__LUI = 64, + C__ADDI16SP = 65, + __reserved_clui = 66, + C__SRLI = 67, + C__SRAI = 68, + C__ANDI = 69, + C__SUB = 70, + C__XOR = 71, + C__OR = 72, + C__AND = 73, + C__J = 74, + C__BEQZ = 75, + C__BNEZ = 76, + C__SLLI = 77, + C__LWSP = 78, + C__MV = 79, + C__JR = 80, + __reserved_cmv = 81, + C__ADD = 82, + C__JALR = 83, + C__EBREAK = 84, + C__SWSP = 85, + DII = 86, MAX_OPCODE }; }; -struct tgc_c: public arch_if { +struct tgc5c: public arch_if { - using virt_addr_t = typename traits::virt_addr_t; - using phys_addr_t = typename traits::phys_addr_t; - using reg_t = typename traits::reg_t; - using addr_t = typename traits::addr_t; + using virt_addr_t = typename traits::virt_addr_t; + using phys_addr_t = typename traits::phys_addr_t; + using reg_t = typename traits::reg_t; + using addr_t = typename traits::addr_t; - tgc_c(); - ~tgc_c(); + tgc5c(); + ~tgc5c(); void reset(uint64_t address=0) override; @@ -203,14 +195,6 @@ struct tgc_c: public arch_if { inline uint64_t stop_code() { return interrupt_sim; } - inline phys_addr_t v2p(const iss::addr_t& addr){ - if (addr.space != traits::MEM || addr.type == iss::address_type::PHYSICAL || - addr_mode[static_cast(addr.access)&0x3]==address_type::PHYSICAL) { - return phys_addr_t(addr.access, addr.space, addr.val&traits::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; } @@ -219,7 +203,7 @@ struct tgc_c: public arch_if { #pragma pack(push, 1) - struct TGC_C_regs { + struct TGC5C_regs { uint32_t X0 = 0; uint32_t X1 = 0; uint32_t X2 = 0; @@ -258,8 +242,10 @@ struct tgc_c: public arch_if { uint32_t DPC = 0; uint32_t trap_state = 0, pending_trap = 0; uint64_t icount = 0; + uint64_t cycle = 0; uint64_t instret = 0; - uint32_t last_branch; + uint32_t instruction = 0; + uint32_t last_branch = 0; } reg; #pragma pack(pop) std::array addr_mode; @@ -273,4 +259,5 @@ struct tgc_c: public arch_if { } } -#endif /* _TGC_C_H_ */ +#endif /* _TGC5C_H_ */ +// clang-format on diff --git a/src/iss/arch/tgc_mapper.h b/src/iss/arch/tgc_mapper.h new file mode 100644 index 0000000..02ebacc --- /dev/null +++ b/src/iss/arch/tgc_mapper.h @@ -0,0 +1,57 @@ +#ifndef _ISS_ARCH_TGC_MAPPER_H +#define _ISS_ARCH_TGC_MAPPER_H + +#include "riscv_hart_m_p.h" +#include "tgc5c.h" +using tgc5c_plat_type = iss::arch::riscv_hart_m_p; +#ifdef CORE_TGC5A +#include "riscv_hart_m_p.h" +#include +using tgc5a_plat_type = iss::arch::riscv_hart_m_p; +#endif +#ifdef CORE_TGC5B +#include "riscv_hart_m_p.h" +#include +using tgc5b_plat_type = iss::arch::riscv_hart_m_p; +#endif +#ifdef CORE_TGC5C_XRB_NN +#include "hwl.h" +#include "riscv_hart_m_p.h" +#include +using tgc5c_xrb_nn_plat_type = iss::arch::hwl>; +#endif +#ifdef CORE_TGC5D +#include "riscv_hart_mu_p.h" +#include +using tgc5d_plat_type = iss::arch::riscv_hart_mu_p; +#endif +#ifdef CORE_TGC5D_XRB_MAC +#include "riscv_hart_mu_p.h" +#include +using tgc5d_xrb_mac_plat_type = + iss::arch::riscv_hart_mu_p; +#endif +#ifdef CORE_TGC5D_XRB_NN +#include "hwl.h" +#include "riscv_hart_mu_p.h" +#include +using tgc5d_xrb_nn_plat_type = + iss::arch::hwl>; +#endif +#ifdef CORE_TGC5E +#include "riscv_hart_mu_p.h" +#include +using tgc5e_plat_type = iss::arch::riscv_hart_mu_p; +#endif +#ifdef CORE_TGC5X +#include "riscv_hart_mu_p.h" +#include +using tgc5x_plat_type = iss::arch::riscv_hart_mu_p; +#endif + +#endif diff --git a/src/iss/arch/wt_cache.h b/src/iss/arch/wt_cache.h new file mode 100644 index 0000000..e762f22 --- /dev/null +++ b/src/iss/arch/wt_cache.h @@ -0,0 +1,171 @@ +/******************************************************************************* + * Copyright (C) 2023 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 implementation + ******************************************************************************/ + +#ifndef _RISCV_HART_M_P_WT_CACHE_H +#define _RISCV_HART_M_P_WT_CACHE_H + +#include +#include +#include +#include +#include + +namespace iss { +namespace arch { +namespace cache { + +enum class state { INVALID, VALID }; +struct line { + uint64_t tag_addr{0}; + state st{state::INVALID}; + std::vector data; + line(unsigned line_sz) + : data(line_sz) {} +}; +struct set { + std::vector ways; + set(unsigned ways_count, line const& l) + : ways(ways_count, l) {} +}; +struct cache { + std::vector sets; + + cache(unsigned size, unsigned line_sz, unsigned ways) { + line const ref_line{line_sz}; + set const ref_set{ways, ref_line}; + sets.resize(size / (ways * line_sz), ref_set); + } +}; + +struct wt_policy { + bool is_cacheline_hit(cache& c); +}; +} // namespace cache + +// write thru, allocate on read, direct mapped or set-associative with round-robin replacement policy +template class wt_cache : public BASE { +public: + using base_class = BASE; + using this_class = wt_cache; + using reg_t = typename BASE::reg_t; + using mem_read_f = typename BASE::mem_read_f; + using mem_write_f = typename BASE::mem_write_f; + using phys_addr_t = typename BASE::phys_addr_t; + + wt_cache(feature_config cfg = feature_config{}); + virtual ~wt_cache() = default; + + unsigned size{4096}; + unsigned line_sz{32}; + unsigned ways{1}; + uint64_t io_address{0xf0000000}; + uint64_t io_addr_mask{0xf0000000}; + +protected: + iss::status read_cache(phys_addr_t addr, unsigned, uint8_t* const); + iss::status write_cache(phys_addr_t addr, unsigned, uint8_t const* const); + std::function cache_mem_rd_delegate; + std::function cache_mem_wr_delegate; + std::unique_ptr dcache_ptr; + std::unique_ptr icache_ptr; + size_t get_way_select() { return 0; } +}; + +template +inline wt_cache::wt_cache(feature_config cfg) +: BASE(cfg) +, io_address{cfg.io_address} +, io_addr_mask{cfg.io_addr_mask} { + auto cb = base_class::replace_mem_access( + [this](phys_addr_t a, unsigned l, uint8_t* const d) -> iss::status { return read_cache(a, l, d); }, + [this](phys_addr_t a, unsigned l, uint8_t const* const d) -> iss::status { return write_cache(a, l, d); }); + cache_mem_rd_delegate = cb.first; + cache_mem_wr_delegate = cb.second; +} + +template iss::status iss::arch::wt_cache::read_cache(phys_addr_t a, unsigned l, uint8_t* const d) { + if(!icache_ptr) { + icache_ptr.reset(new cache::cache(size, line_sz, ways)); + dcache_ptr.reset(new cache::cache(size, line_sz, ways)); + } + if((a.val & io_addr_mask) != io_address) { + auto set_addr = (a.val & (size - 1)) >> util::ilog2(line_sz * ways); + auto tag_addr = a.val >> util::ilog2(line_sz); + auto& set = (is_fetch(a.access) ? icache_ptr : dcache_ptr)->sets[set_addr]; + for(auto& cl : set.ways) { + if(cl.st == cache::state::VALID && cl.tag_addr == tag_addr) { + auto start_addr = a.val & (line_sz - 1); + for(auto i = 0U; i < l; ++i) + d[i] = cl.data[start_addr + i]; + return iss::Ok; + } + } + auto& cl = set.ways[get_way_select()]; + phys_addr_t cl_addr{a}; + cl_addr.val = tag_addr << util::ilog2(line_sz); + cache_mem_rd_delegate(cl_addr, line_sz, cl.data.data()); + cl.tag_addr = tag_addr; + cl.st = cache::state::VALID; + auto start_addr = a.val & (line_sz - 1); + for(auto i = 0U; i < l; ++i) + d[i] = cl.data[start_addr + i]; + return iss::Ok; + } else + return cache_mem_rd_delegate(a, l, d); +} + +template iss::status iss::arch::wt_cache::write_cache(phys_addr_t a, unsigned l, const uint8_t* const d) { + if(!dcache_ptr) + dcache_ptr.reset(new cache::cache(size, line_sz, ways)); + auto res = cache_mem_wr_delegate(a, l, d); + if(res == iss::Ok && ((a.val & io_addr_mask) != io_address)) { + auto set_addr = (a.val & (size - 1)) >> util::ilog2(line_sz * ways); + auto tag_addr = a.val >> util::ilog2(line_sz); + auto& set = dcache_ptr->sets[set_addr]; + for(auto& cl : set.ways) { + if(cl.st == cache::state::VALID && cl.tag_addr == tag_addr) { + auto start_addr = a.val & (line_sz - 1); + for(auto i = 0U; i < l; ++i) + cl.data[start_addr + i] = d[i]; + break; + } + } + } + return res; +} + +} // namespace arch +} // namespace iss + +#endif /* _RISCV_HART_M_P_H */ diff --git a/incl/iss/debugger/riscv_target_adapter.h b/src/iss/debugger/riscv_target_adapter.h similarity index 70% rename from incl/iss/debugger/riscv_target_adapter.h rename to src/iss/debugger/riscv_target_adapter.h index b7c3036..6a2a527 100644 --- a/incl/iss/debugger/riscv_target_adapter.h +++ b/src/iss/debugger/riscv_target_adapter.h @@ -53,20 +53,20 @@ using namespace iss::debugger; template class riscv_target_adapter : public target_adapter_base { public: - riscv_target_adapter(server_if *srv, iss::arch_if *core) + riscv_target_adapter(server_if* srv, iss::arch_if* core) : target_adapter_base(srv) , core(core) {} /*============== Thread Control ===============================*/ /* Set generic thread */ - status set_gen_thread(rp_thread_ref &thread) override; + status set_gen_thread(rp_thread_ref& thread) override; /* Set control thread */ - status set_ctrl_thread(rp_thread_ref &thread) override; + status set_ctrl_thread(rp_thread_ref& thread) override; /* Get thread status */ - status is_thread_alive(rp_thread_ref &thread, bool &alive) override; + status is_thread_alive(rp_thread_ref& thread, bool& alive) override; /*============= Register Access ================================*/ @@ -74,79 +74,77 @@ public: target byte order. If register is not available corresponding bytes in avail_buf are 0, otherwise avail buf is 1 */ - status read_registers(std::vector &data, std::vector &avail) override; + status read_registers(std::vector& data, std::vector& avail) override; /* Write all registers. buf is 4-byte aligned and it is in target byte order */ - status write_registers(const std::vector &data) override; + status write_registers(const std::vector& data) override; /* Read one register. buf is 4-byte aligned and it is in target byte order. If register is not available corresponding bytes in avail_buf are 0, otherwise avail buf is 1 */ - status read_single_register(unsigned int reg_no, std::vector &buf, - std::vector &avail_buf) override; + status read_single_register(unsigned int reg_no, std::vector& buf, std::vector& avail_buf) override; /* Write one register. buf is 4-byte aligned and it is in target byte order */ - status write_single_register(unsigned int reg_no, const std::vector &buf) override; + status write_single_register(unsigned int reg_no, const std::vector& buf) override; /*=================== Memory Access =====================*/ /* Read memory, buf is 4-bytes aligned and it is in target byte order */ - status read_mem(uint64_t addr, std::vector &buf) override; + status read_mem(uint64_t addr, std::vector& buf) override; /* Write memory, buf is 4-bytes aligned and it is in target byte order */ - status write_mem(uint64_t addr, const std::vector &buf) override; + status write_mem(uint64_t addr, const std::vector& buf) override; - status process_query(unsigned int &mask, const rp_thread_ref &arg, rp_thread_info &info) override; + status process_query(unsigned int& mask, const rp_thread_ref& arg, rp_thread_info& info) override; - status thread_list_query(int first, const rp_thread_ref &arg, std::vector &result, size_t max_num, - size_t &num, bool &done) override; + status thread_list_query(int first, const rp_thread_ref& arg, std::vector& result, size_t max_num, size_t& num, + bool& done) override; - status current_thread_query(rp_thread_ref &thread) override; + status current_thread_query(rp_thread_ref& thread) override; - status offsets_query(uint64_t &text, uint64_t &data, uint64_t &bss) override; + status offsets_query(uint64_t& text, uint64_t& data, uint64_t& bss) override; - status crc_query(uint64_t addr, size_t len, uint32_t &val) override; + status crc_query(uint64_t addr, size_t len, uint32_t& val) override; - status raw_query(std::string in_buf, std::string &out_buf) override; + status raw_query(std::string in_buf, std::string& out_buf) override; - status threadinfo_query(int first, std::string &out_buf) override; + status threadinfo_query(int first, std::string& out_buf) override; - status threadextrainfo_query(const rp_thread_ref &thread, std::string &out_buf) override; + status threadextrainfo_query(const rp_thread_ref& thread, std::string& out_buf) override; - status packetsize_query(std::string &out_buf) override; + status packetsize_query(std::string& out_buf) override; - status add_break(int type, uint64_t addr, unsigned int length) override; + status add_break(break_type type, uint64_t addr, unsigned int length) override; - status remove_break(int type, uint64_t addr, unsigned int length) override; + status remove_break(break_type type, uint64_t addr, unsigned int length) override; - status resume_from_addr(bool step, int sig, uint64_t addr, rp_thread_ref thread, - std::function stop_callback) override; + status resume_from_addr(bool step, int sig, uint64_t addr, rp_thread_ref thread, std::function stop_callback) override; - status target_xml_query(std::string &out_buf) override; + status target_xml_query(std::string& out_buf) override; protected: - static inline constexpr addr_t map_addr(const addr_t &i) { return i; } + static inline constexpr addr_t map_addr(const addr_t& i) { return i; } - iss::arch_if *core; + iss::arch_if* core; rp_thread_ref thread_idx; }; -template status riscv_target_adapter::set_gen_thread(rp_thread_ref &thread) { +template status riscv_target_adapter::set_gen_thread(rp_thread_ref& thread) { thread_idx = thread; return Ok; } -template status riscv_target_adapter::set_ctrl_thread(rp_thread_ref &thread) { +template status riscv_target_adapter::set_ctrl_thread(rp_thread_ref& thread) { thread_idx = thread; return Ok; } -template status riscv_target_adapter::is_thread_alive(rp_thread_ref &thread, bool &alive) { +template status riscv_target_adapter::is_thread_alive(rp_thread_ref& thread, bool& alive) { alive = 1; return Ok; } @@ -158,10 +156,9 @@ template status riscv_target_adapter::is_thread_alive(rp_t * set if all threads are processed. */ template -status riscv_target_adapter::thread_list_query(int first, const rp_thread_ref &arg, - std::vector &result, size_t max_num, size_t &num, - bool &done) { - if (first == 0) { +status riscv_target_adapter::thread_list_query(int first, const rp_thread_ref& arg, std::vector& result, + size_t max_num, size_t& num, bool& done) { + if(first == 0) { result.clear(); result.push_back(thread_idx); num = 1; @@ -171,58 +168,57 @@ status riscv_target_adapter::thread_list_query(int first, const rp_thread_ return NotSupported; } -template status riscv_target_adapter::current_thread_query(rp_thread_ref &thread) { +template status riscv_target_adapter::current_thread_query(rp_thread_ref& thread) { thread = thread_idx; return Ok; } -template -status riscv_target_adapter::read_registers(std::vector &data, std::vector &avail) { +template status riscv_target_adapter::read_registers(std::vector& data, std::vector& avail) { LOG(TRACE) << "reading target registers"; // return idx<0?:; data.clear(); avail.clear(); - const uint8_t *reg_base = core->get_regs_base_ptr(); - auto start_reg=arch::traits::X0; - for (size_t reg_no = start_reg; reg_no < start_reg+33/*arch::traits::NUM_REGS*/; ++reg_no) { + const uint8_t* reg_base = core->get_regs_base_ptr(); + auto start_reg = arch::traits::X0; + for(size_t reg_no = start_reg; reg_no < start_reg + 33 /*arch::traits::NUM_REGS*/; ++reg_no) { auto reg_width = arch::traits::reg_bit_widths[reg_no] / 8; unsigned offset = traits::reg_byte_offsets[reg_no]; - for (size_t j = 0; j < reg_width; ++j) { + for(size_t j = 0; j < reg_width; ++j) { data.push_back(*(reg_base + offset + j)); avail.push_back(0xff); } } // work around fill with F type registers -// if (arch::traits::NUM_REGS < 65) { -// auto reg_width = sizeof(typename arch::traits::reg_t); -// for (size_t reg_no = 0; reg_no < 33; ++reg_no) { -// for (size_t j = 0; j < reg_width; ++j) { -// data.push_back(0x0); -// avail.push_back(0x00); -// } -// // if(arch::traits::XLEN < 64) -// // for(unsigned j=0; j<4; ++j){ -// // data.push_back(0x0); -// // avail.push_back(0x00); -// // } -// } -// } + // if (arch::traits::NUM_REGS < 65) { + // auto reg_width = sizeof(typename arch::traits::reg_t); + // for (size_t reg_no = 0; reg_no < 33; ++reg_no) { + // for (size_t j = 0; j < reg_width; ++j) { + // data.push_back(0x0); + // avail.push_back(0x00); + // } + // // if(arch::traits::XLEN < 64) + // // for(unsigned j=0; j<4; ++j){ + // // data.push_back(0x0); + // // avail.push_back(0x00); + // // } + // } + // } return Ok; } -template status riscv_target_adapter::write_registers(const std::vector &data) { - auto start_reg=arch::traits::X0; - auto *reg_base = core->get_regs_base_ptr(); +template status riscv_target_adapter::write_registers(const std::vector& data) { + auto start_reg = arch::traits::X0; + auto* reg_base = core->get_regs_base_ptr(); auto iter = data.data(); - bool e_ext = arch::traits::PC<32; - for (size_t reg_no = 0; reg_no < start_reg+33/*arch::traits::NUM_REGS*/; ++reg_no) { - if(e_ext && reg_no>15){ - if(reg_no==32){ + bool e_ext = arch::traits::PC < 32; + for(size_t reg_no = 0; reg_no < start_reg + 33 /*arch::traits::NUM_REGS*/; ++reg_no) { + if(e_ext && reg_no > 15) { + if(reg_no == 32) { auto reg_width = arch::traits::reg_bit_widths[arch::traits::PC] / 8; auto offset = traits::reg_byte_offsets[arch::traits::PC]; std::copy(iter, iter + reg_width, reg_base); } else { - const uint64_t zero_val=0; + const uint64_t zero_val = 0; auto reg_width = arch::traits::reg_bit_widths[15] / 8; auto iter = (uint8_t*)&zero_val; std::copy(iter, iter + reg_width, reg_base); @@ -239,12 +235,11 @@ template status riscv_target_adapter::write_registers(cons } template -status riscv_target_adapter::read_single_register(unsigned int reg_no, std::vector &data, - std::vector &avail) { - if (reg_no < 65) { +status riscv_target_adapter::read_single_register(unsigned int reg_no, std::vector& data, std::vector& avail) { + if(reg_no < 65) { // auto reg_size = arch::traits::reg_bit_width(static_cast::reg_e>(reg_no))/8; - auto *reg_base = core->get_regs_base_ptr(); + auto* reg_base = core->get_regs_base_ptr(); auto reg_width = arch::traits::reg_bit_widths[reg_no] / 8; data.resize(reg_width); avail.resize(reg_width); @@ -261,10 +256,9 @@ status riscv_target_adapter::read_single_register(unsigned int reg_no, std return data.size() > 0 ? Ok : Err; } -template -status riscv_target_adapter::write_single_register(unsigned int reg_no, const std::vector &data) { - if (reg_no < 65) { - auto *reg_base = core->get_regs_base_ptr(); +template status riscv_target_adapter::write_single_register(unsigned int reg_no, const std::vector& data) { + if(reg_no < 65) { + auto* reg_base = core->get_regs_base_ptr(); auto reg_width = arch::traits::reg_bit_widths[static_cast::reg_e>(reg_no)] / 8; auto offset = traits::reg_byte_offsets[reg_no]; std::copy(data.begin(), data.begin() + reg_width, reg_base + offset); @@ -275,41 +269,36 @@ status riscv_target_adapter::write_single_register(unsigned int reg_no, co return Ok; } -template status riscv_target_adapter::read_mem(uint64_t addr, std::vector &data) { +template status riscv_target_adapter::read_mem(uint64_t addr, std::vector& data) { auto a = map_addr({iss::access_type::DEBUG_READ, iss::address_type::VIRTUAL, 0, addr}); auto f = [&]() -> status { return core->read(a, data.size(), data.data()); }; return srv->execute_syncronized(f); } -template status riscv_target_adapter::write_mem(uint64_t addr, const std::vector &data) { +template status riscv_target_adapter::write_mem(uint64_t addr, const std::vector& data) { auto a = map_addr({iss::access_type::DEBUG_READ, iss::address_type::VIRTUAL, 0, addr}); auto f = [&]() -> status { return core->write(a, data.size(), data.data()); }; return srv->execute_syncronized(f); } template -status riscv_target_adapter::process_query(unsigned int &mask, const rp_thread_ref &arg, rp_thread_info &info) { +status riscv_target_adapter::process_query(unsigned int& mask, const rp_thread_ref& arg, rp_thread_info& info) { return NotSupported; } -template -status riscv_target_adapter::offsets_query(uint64_t &text, uint64_t &data, uint64_t &bss) { +template status riscv_target_adapter::offsets_query(uint64_t& text, uint64_t& data, uint64_t& bss) { text = 0; data = 0; bss = 0; return Ok; } -template status riscv_target_adapter::crc_query(uint64_t addr, size_t len, uint32_t &val) { - return NotSupported; -} +template status riscv_target_adapter::crc_query(uint64_t addr, size_t len, uint32_t& val) { return NotSupported; } -template status riscv_target_adapter::raw_query(std::string in_buf, std::string &out_buf) { - return NotSupported; -} +template status riscv_target_adapter::raw_query(std::string in_buf, std::string& out_buf) { return NotSupported; } -template status riscv_target_adapter::threadinfo_query(int first, std::string &out_buf) { - if (first) { +template status riscv_target_adapter::threadinfo_query(int first, std::string& out_buf) { + if(first) { out_buf = fmt::format("m{:x}", thread_idx.val); } else { out_buf = "l"; @@ -317,8 +306,7 @@ template status riscv_target_adapter::threadinfo_query(int return Ok; } -template -status riscv_target_adapter::threadextrainfo_query(const rp_thread_ref &thread, std::string &out_buf) { +template status riscv_target_adapter::threadextrainfo_query(const rp_thread_ref& thread, std::string& out_buf) { std::array buf; memset(buf.data(), 0, 20); sprintf(buf.data(), "%02x%02x%02x%02x%02x%02x%02x%02x%02x", 'R', 'u', 'n', 'n', 'a', 'b', 'l', 'e', 0); @@ -326,48 +314,61 @@ status riscv_target_adapter::threadextrainfo_query(const rp_thread_ref &th return Ok; } -template status riscv_target_adapter::packetsize_query(std::string &out_buf) { +template status riscv_target_adapter::packetsize_query(std::string& out_buf) { out_buf = "PacketSize=1000"; return Ok; } -template status riscv_target_adapter::add_break(int type, uint64_t addr, unsigned int length) { - auto saddr = map_addr({iss::access_type::FETCH, iss::address_type::PHYSICAL, 0, addr}); - auto eaddr = map_addr({iss::access_type::FETCH, iss::address_type::PHYSICAL, 0, addr + length}); - target_adapter_base::bp_lut.addEntry(++target_adapter_base::bp_count, saddr.val, eaddr.val - saddr.val); - LOG(TRACE) << "Adding breakpoint with handle " << target_adapter_base::bp_count << " for addr 0x" << std::hex - << saddr.val << std::dec; - LOG(TRACE) << "Now having " << target_adapter_base::bp_lut.size() << " breakpoints"; - return Ok; -} - -template status riscv_target_adapter::remove_break(int type, uint64_t addr, unsigned int length) { - auto saddr = map_addr({iss::access_type::FETCH, iss::address_type::PHYSICAL, 0, addr}); - unsigned handle = target_adapter_base::bp_lut.getEntry(saddr.val); - if (handle) { - LOG(TRACE) << "Removing breakpoint with handle " << handle << " for addr 0x" << std::hex << saddr.val +template status riscv_target_adapter::add_break(break_type type, uint64_t addr, unsigned int length) { + switch(type) { + default: + return Err; + case SW_EXEC: + case HW_EXEC: { + auto saddr = map_addr({iss::access_type::FETCH, iss::address_type::PHYSICAL, 0, addr}); + auto eaddr = map_addr({iss::access_type::FETCH, iss::address_type::PHYSICAL, 0, addr + length}); + target_adapter_base::bp_lut.addEntry(++target_adapter_base::bp_count, saddr.val, eaddr.val - saddr.val); + LOG(TRACE) << "Adding breakpoint with handle " << target_adapter_base::bp_count << " for addr 0x" << std::hex << saddr.val << std::dec; - // TODO: check length of addr range - target_adapter_base::bp_lut.removeEntry(handle); LOG(TRACE) << "Now having " << target_adapter_base::bp_lut.size() << " breakpoints"; return Ok; } - LOG(TRACE) << "Now having " << target_adapter_base::bp_lut.size() << " breakpoints"; - return Err; + } +} + +template status riscv_target_adapter::remove_break(break_type type, uint64_t addr, unsigned int length) { + switch(type) { + default: + return Err; + case SW_EXEC: + case HW_EXEC: { + auto saddr = map_addr({iss::access_type::FETCH, iss::address_type::PHYSICAL, 0, addr}); + unsigned handle = target_adapter_base::bp_lut.getEntry(saddr.val); + if(handle) { + LOG(TRACE) << "Removing breakpoint with handle " << handle << " for addr 0x" << std::hex << saddr.val << std::dec; + // TODO: check length of addr range + target_adapter_base::bp_lut.removeEntry(handle); + LOG(TRACE) << "Now having " << target_adapter_base::bp_lut.size() << " breakpoints"; + return Ok; + } + LOG(TRACE) << "Now having " << target_adapter_base::bp_lut.size() << " breakpoints"; + return Err; + } + } } template status riscv_target_adapter::resume_from_addr(bool step, int sig, uint64_t addr, rp_thread_ref thread, std::function stop_callback) { - auto *reg_base = core->get_regs_base_ptr(); + auto* reg_base = core->get_regs_base_ptr(); auto reg_width = arch::traits::reg_bit_widths[arch::traits::PC] / 8; auto offset = traits::reg_byte_offsets[arch::traits::PC]; - const uint8_t *iter = reinterpret_cast(&addr); + const uint8_t* iter = reinterpret_cast(&addr); std::copy(iter, iter + reg_width, reg_base); return resume_from_current(step, sig, thread, stop_callback); } -template status riscv_target_adapter::target_xml_query(std::string &out_buf) { +template status riscv_target_adapter::target_xml_query(std::string& out_buf) { const std::string res{"" "riscv:rv32" //" \n" @@ -454,7 +455,7 @@ template status riscv_target_adapter::target_xml_query(std */ -} -} +} // namespace debugger +} // namespace iss #endif /* _ISS_DEBUGGER_RISCV_TARGET_ADAPTER_H_ */ diff --git a/incl/iss/factory.h b/src/iss/factory.h similarity index 59% rename from incl/iss/factory.h rename to src/iss/factory.h index 1664e38..a2a1943 100644 --- a/incl/iss/factory.h +++ b/src/iss/factory.h @@ -33,15 +33,20 @@ #ifndef _ISS_FACTORY_H_ #define _ISS_FACTORY_H_ +#include +#include #include +#include +#include +#include +#include namespace iss { using cpu_ptr = std::unique_ptr; -using vm_ptr= std::unique_ptr; +using vm_ptr = std::unique_ptr; -template -std::tuple create_cpu(std::string const& backend, unsigned gdb_port){ +template std::tuple create_cpu(std::string const& backend, unsigned gdb_port) { using core_type = typename PLAT::core; core_type* lcpu = new PLAT(); if(backend == "interp") @@ -50,13 +55,52 @@ std::tuple create_cpu(std::string const& backend, unsigned gdb_ if(backend == "llvm") return {cpu_ptr{lcpu}, vm_ptr{iss::llvm::create(lcpu, gdb_port)}}; #endif -#ifdef WITH_LLVM +#ifdef WITH_TCC if(backend == "tcc") return {cpu_ptr{lcpu}, vm_ptr{iss::tcc::create(lcpu, gdb_port)}}; #endif return {nullptr, nullptr}; } -} +class core_factory { + using cpu_ptr = std::unique_ptr; + using vm_ptr = std::unique_ptr; + using base_t = std::tuple; + using create_fn = std::function; + using registry_t = std::unordered_map; + + registry_t registry; + + core_factory() = default; + core_factory(const core_factory&) = delete; + core_factory& operator=(const core_factory&) = delete; + +public: + static core_factory& instance() { + static core_factory bf; + return bf; + } + + bool register_creator(const std::string& className, create_fn const& fn) { + registry[className] = fn; + return true; + } + + base_t create(std::string const& className, unsigned gdb_port = 0, void* init_data = nullptr) const { + registry_t::const_iterator regEntry = registry.find(className); + if(regEntry != registry.end()) + return regEntry->second(gdb_port, init_data); + return {nullptr, nullptr}; + } + + std::vector get_names() { + std::vector keys{registry.size()}; + std::transform(std::begin(registry), std::end(registry), std::begin(keys), + [](std::pair const& p) { return p.first; }); + return keys; + } +}; + +} // namespace iss #endif /* _ISS_FACTORY_H_ */ diff --git a/src/iss/plugin/README.md b/src/iss/plugin/README.md new file mode 100644 index 0000000..87f7db3 --- /dev/null +++ b/src/iss/plugin/README.md @@ -0,0 +1,8 @@ +# pctrace + +Trace functionality to allow visualizing coverage in lcov and cachegrind tools. Use environment variables NOCOMPRES and REGDUMP to toggle functionality. +- NOCOMPRES: any value turns off the LZ4 compression +- REGDUMP: any value switches to tracing the registers instead. Also turns off compression. + +Known Bugs: +- currently does not work correctly with jit backends, the plugin cant tell if instructions are compressed. Additionaly the cost of instrs that raise a trap is not known. It takes the cost of the instrid -1 (0 at the moment). diff --git a/src/iss/plugin/cycle_estimate.cpp b/src/iss/plugin/cycle_estimate.cpp new file mode 100644 index 0000000..69e466a --- /dev/null +++ b/src/iss/plugin/cycle_estimate.cpp @@ -0,0 +1,114 @@ +/******************************************************************************* + * Copyright (C) 2017 - 2023, 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 "cycle_estimate.h" +#include +#include + +#include +#include +#include + +using namespace std; + +iss::plugin::cycle_estimate::cycle_estimate(string const& config_file_name) +: instr_if(nullptr) +, config_file_name(config_file_name) {} + +iss::plugin::cycle_estimate::~cycle_estimate() = default; + +bool iss::plugin::cycle_estimate::registration(const char* const version, vm_if& vm) { + instr_if = vm.get_arch()->get_instrumentation_if(); + assert(instr_if && "No instrumentation interface available but callback executed"); + reg_base_ptr = reinterpret_cast(vm.get_arch()->get_regs_base_ptr()); + if(!instr_if) + return false; + const string core_name = instr_if->core_type_name(); + if(config_file_name.length() > 0) { + std::ifstream is(config_file_name); + if(is.is_open()) { + try { + auto root = YAML::LoadAll(is); + if(root.size() != 1) { + LOG(ERR) << "Too many root nodes in YAML file " << config_file_name; + } + for(auto p : root[0]) { + auto isa_subset = p.first; + auto instructions = p.second; + for(auto const& instr : instructions) { + auto idx = instr.second["index"].as(); + if(delays.size() <= idx) + delays.resize(idx + 1); + auto& res = delays[idx]; + res.is_branch = instr.second["branch"].as(); + auto delay = instr.second["delay"]; + if(delay.IsSequence()) { + res.not_taken = delay[0].as(); + res.taken = delay[1].as(); + } else { + try { + res.not_taken = delay.as(); + res.taken = res.not_taken; + } catch(const YAML::BadConversion& e) { + res.f = iss::plugin::calculator(reg_base_ptr, delay.as()); + } + } + } + } + } catch(YAML::ParserException& e) { + LOG(ERR) << "Could not parse input file " << config_file_name << ", reason: " << e.what(); + return false; + } + } else { + LOG(ERR) << "Could not open input file " << config_file_name; + return false; + } + } + return true; +} + +void iss::plugin::cycle_estimate::callback(instr_info_t instr_info) { + size_t instr_id = instr_info.instr_id; + auto& entry = instr_id < delays.size() ? delays[instr_id] : illegal_desc; + if(instr_info.phase_id == PRE_SYNC) { + if(entry.f) + current_delay = entry.f(instr_if->get_instr_word()); + } else { + if(!entry.f) + current_delay = instr_if->is_branch_taken() ? entry.taken : entry.not_taken; + if(current_delay > 1) + instr_if->update_last_instr_cycles(current_delay); + current_delay = 1; + } +} diff --git a/incl/iss/plugin/cycle_estimate.h b/src/iss/plugin/cycle_estimate.h similarity index 71% rename from incl/iss/plugin/cycle_estimate.h rename to src/iss/plugin/cycle_estimate.h index 0c2cc15..c2f6d13 100644 --- a/incl/iss/plugin/cycle_estimate.h +++ b/src/iss/plugin/cycle_estimate.h @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (C) 2017, 2018, MINRES Technologies GmbH + * Copyright (C) 2017 - 2023, MINRES Technologies GmbH * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -37,6 +37,7 @@ #include "iss/instrumentation_if.h" #include "iss/vm_plugin.h" +#include #include #include #include @@ -45,46 +46,44 @@ namespace iss { namespace plugin { -class cycle_estimate: public iss::vm_plugin { - BEGIN_BF_DECL(instr_desc, uint32_t) - BF_FIELD(taken, 24, 8) - BF_FIELD(not_taken, 16, 8) - BF_FIELD(is_branch, 8, 8) - BF_FIELD(size, 0, 8) - instr_desc(uint32_t size, uint32_t taken, uint32_t not_taken, bool branch): instr_desc() { - this->size=size; - this->taken=taken; - this->not_taken=not_taken; - this->is_branch=branch; - } - END_BF_DECL(); +class cycle_estimate : public vm_plugin { + struct instr_desc { + size_t size{0}; + bool is_branch{false}; + unsigned not_taken{1}; + unsigned taken{1}; + std::function f; + }; public: cycle_estimate() = delete; - cycle_estimate(const cycle_estimate &) = delete; + cycle_estimate(const cycle_estimate&) = delete; - cycle_estimate(const cycle_estimate &&) = delete; + cycle_estimate(const cycle_estimate&&) = delete; cycle_estimate(std::string const& config_file_name); virtual ~cycle_estimate(); - cycle_estimate &operator=(const cycle_estimate &) = delete; + cycle_estimate& operator=(const cycle_estimate&) = delete; - cycle_estimate &operator=(const cycle_estimate &&) = delete; + cycle_estimate& operator=(const cycle_estimate&&) = delete; - bool registration(const char *const version, vm_if &arch) override; + bool registration(const char* const version, vm_if& arch) override; - sync_type get_sync() override { return POST_SYNC; }; + sync_type get_sync() override { return ALL_SYNC; }; - void callback(instr_info_t instr_info, exec_info const&) override; + void callback(instr_info_t instr_info) override; private: - iss::instrumentation_if *arch_instr; + iss::instrumentation_if* instr_if{nullptr}; + uint32_t* reg_base_ptr{nullptr}; + instr_desc illegal_desc{}; std::vector delays; + unsigned current_delay{0}; struct pair_hash { - size_t operator()(const std::pair &p) const { + size_t operator()(const std::pair& p) const { std::hash hash; return hash(p.first) + hash(p.second); } @@ -92,7 +91,7 @@ private: std::unordered_map, uint64_t, pair_hash> blocks; std::string config_file_name; }; -} -} +} // namespace plugin +} // namespace iss #endif /* _ISS_PLUGIN_CYCLE_ESTIMATE_H_ */ diff --git a/src/plugin/instruction_count.cpp b/src/iss/plugin/instruction_count.cpp similarity index 58% rename from src/plugin/instruction_count.cpp rename to src/iss/plugin/instruction_count.cpp index aba30eb..bb47e53 100644 --- a/src/plugin/instruction_count.cpp +++ b/src/iss/plugin/instruction_count.cpp @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (C) 2017, MINRES Technologies GmbH + * Copyright (C) 2017 - 2023 MINRES Technologies GmbH * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -32,64 +32,65 @@ * eyck@minres.com - initial API and implementation ******************************************************************************/ -#include "iss/plugin/instruction_count.h" -#include "iss/instrumentation_if.h" +#include "instruction_count.h" +#include +#include +#include #include #include -#include iss::plugin::instruction_count::instruction_count(std::string config_file_name) { - if (config_file_name.length() > 0) { + if(config_file_name.length() > 0) { std::ifstream is(config_file_name); - if (is.is_open()) { + if(is.is_open()) { try { - is >> root; - } catch (Json::RuntimeError &e) { - LOG(ERR) << "Could not parse input file " << config_file_name << ", reason: " << e.what(); + auto root = YAML::LoadAll(is); + if(root.size() != 1) { + LOG(ERR) << "Too many rro nodes in YAML file " << config_file_name; + } + for(auto p : root[0]) { + auto isa_subset = p.first; + auto instructions = p.second; + for(auto const& instr : instructions) { + instr_delay res; + res.instr_name = instr.first.as(); + res.size = instr.second["encoding"].as().size() - 2; // not counting 0b + auto delay = instr.second["delay"]; + if(delay.IsSequence()) { + res.not_taken_delay = delay[0].as(); + res.taken_delay = delay[1].as(); + } else { + res.not_taken_delay = delay.as(); + res.taken_delay = res.not_taken_delay; + } + delays.push_back(std::move(res)); + } + } + rep_counts.resize(delays.size()); + } catch(YAML::ParserException& e) { + LOG(ERR) << "Could not parse input file " << config_file_name << ", reason: " << e.what(); } } else { - LOG(ERR) << "Could not open input file " << config_file_name; + LOG(ERR) << "Could not open input file " << config_file_name; } } } iss::plugin::instruction_count::~instruction_count() { - size_t idx=0; - for(auto it:delays){ - if(rep_counts[idx]>0) - LOG(INFO)< 0 && it.instr_name.find("__" != 0)) + LOG(INFO) << it.instr_name << ";" << rep_counts[idx]; + idx++; + } } bool iss::plugin::instruction_count::registration(const char* const version, vm_if& vm) { auto instr_if = vm.get_arch()->get_instrumentation_if(); - if(!instr_if) return false; - const std::string core_name = instr_if->core_type_name(); - Json::Value &val = root[core_name]; - if(!val.isNull() && val.isArray()){ - delays.reserve(val.size()); - for(auto it:val){ - auto name = it["name"]; - auto size = it["size"]; - auto delay = it["delay"]; - if(!name.isString() || !size.isUInt() || !(delay.isUInt() || delay.isArray())) throw std::runtime_error("JSON parse error"); - if(delay.isUInt()){ - const instr_delay entry{name.asCString(), size.asUInt(), delay.asUInt(), 0}; - delays.push_back(entry); - } else { - const instr_delay entry{name.asCString(), size.asUInt(), delay[0].asUInt(), delay[1].asUInt()}; - delays.push_back(entry); - } - } - rep_counts.resize(delays.size()); - } else { - LOG(ERR)<<"plugin instruction_count: could not find an entry for "< -#include #include +#include namespace iss { namespace plugin { @@ -53,30 +53,29 @@ class instruction_count : public iss::vm_plugin { public: instruction_count() = delete; - instruction_count(const instruction_count &) = delete; + instruction_count(const instruction_count&) = delete; - instruction_count(const instruction_count &&) = delete; + instruction_count(const instruction_count&&) = delete; instruction_count(std::string config_file_name); virtual ~instruction_count(); - instruction_count &operator=(const instruction_count &) = delete; + instruction_count& operator=(const instruction_count&) = delete; - instruction_count &operator=(const instruction_count &&) = delete; + instruction_count& operator=(const instruction_count&&) = delete; - bool registration(const char *const version, vm_if &arch) override; + bool registration(const char* const version, vm_if& arch) override; sync_type get_sync() override { return POST_SYNC; }; - void callback(instr_info_t, exec_info const&) override; + void callback(instr_info_t) override; private: - Json::Value root; std::vector delays; std::vector rep_counts; }; -} -} +} // namespace plugin +} // namespace iss #endif /* _ISS_PLUGIN_INSTRUCTION_COUNTER_H_ */ diff --git a/src/main.cpp b/src/main.cpp index bbde374..61f3947 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -30,27 +30,30 @@ * *******************************************************************************/ +#include #include #include +#include +#include "iss/arch/tgc_mapper.h" #include #include -#include #ifdef WITH_LLVM -#include +#include #endif +#include "iss/plugin/cycle_estimate.h" +#include "iss/plugin/instruction_count.h" #include -#include -#include -#include +#ifndef WIN32 #include +#endif #if defined(HAS_LUA) #include #endif namespace po = boost::program_options; -int main(int argc, char *argv[]) { +int main(int argc, char* argv[]) { /* * Define and parse the program options */ @@ -59,29 +62,29 @@ int main(int argc, char *argv[]) { // clang-format off desc.add_options() ("help,h", "Print help message") - ("verbose,v", po::value()->implicit_value(0), "Sets logging verbosity") - ("logfile,f", po::value(), "Sets default log file.") + ("verbose,v", po::value()->default_value(4), "Sets logging verbosity") + ("logfile,l", po::value(), "Sets default log file.") ("disass,d", po::value()->implicit_value(""), "Enables disassembly") ("gdb-port,g", po::value()->default_value(0), "enable gdb server and specify port to use") ("instructions,i", po::value()->default_value(std::numeric_limits::max()), "max. number of instructions to simulate") ("reset,r", po::value(), "reset address") ("dump-ir", "dump the intermediate representation") - ("elf", po::value>(), "ELF file(s) to load") + ("elf,f", po::value>(), "ELF file(s) to load") ("mem,m", po::value(), "the memory input file") ("plugin,p", po::value>(), "plugin to activate") - ("backend", po::value()->default_value("interp"), "the memory input file") - ("isa", po::value()->default_value("tgc_c"), "isa to use for simulation"); + ("backend", po::value()->default_value("interp"), "the ISS backend to use, options are: interp, tcc") + ("isa", po::value()->default_value("tgc5c"), "core or isa name to use for simulation, use '?' to get list"); // clang-format on auto parsed = po::command_line_parser(argc, argv).options(desc).allow_unregistered().run(); try { po::store(parsed, clim); // can throw // --help option - if (clim.count("help")) { - std::cout << "DBT-RISE-RiscV simulator for RISC-V" << std::endl << desc << std::endl; + if(clim.count("help")) { + std::cout << "DBT-RISE-TGC simulator for TGC RISC-V cores" << std::endl << desc << std::endl; return 0; } po::notify(clim); // throws on error, so do after help in case - } catch (po::error &e) { + } catch(po::error& e) { // there are problems std::cerr << "ERROR: " << e.what() << std::endl << std::endl; std::cerr << desc << std::endl; @@ -91,19 +94,17 @@ int main(int argc, char *argv[]) { LOGGER(DEFAULT)::print_time() = false; LOGGER(connection)::print_time() = false; - if (clim.count("verbose")) { - auto l = logging::as_log_level(clim["verbose"].as()); - LOGGER(DEFAULT)::reporting_level() = l; - LOGGER(connection)::reporting_level() = l; - } - if (clim.count("logfile")) { + auto l = logging::as_log_level(clim["verbose"].as()); + LOGGER(DEFAULT)::reporting_level() = l; + LOGGER(connection)::reporting_level() = l; + if(clim.count("logfile")) { // configure the connection logger auto f = fopen(clim["logfile"].as().c_str(), "w"); LOG_OUTPUT(DEFAULT)::stream() = f; LOG_OUTPUT(connection)::stream() = f; } - std::vector plugin_list; + std::vector plugin_list; auto res = 0; try { #ifdef WITH_LLVM @@ -111,125 +112,111 @@ int main(int argc, char *argv[]) { iss::init_jit_debug(argc, argv); #endif bool dump = clim.count("dump-ir"); + auto& f = iss::core_factory::instance(); // instantiate the simulator iss::vm_ptr vm{nullptr}; iss::cpu_ptr cpu{nullptr}; std::string isa_opt(clim["isa"].as()); - if (isa_opt == "tgc_c") { - std::tie(cpu, vm) = - iss::create_cpu(clim["backend"].as(), clim["gdb-port"].as()); - } else -#ifdef CORE_TGC_B - if (isa_opt == "tgc_b") { - std::tie(cpu, vm) = - iss::create_cpu(clim["backend"].as(), clim["gdb-port"].as()); - } else -#endif -#ifdef CORE_TGC_C_XRB_NN - if (isa_opt == "tgc_c_xrb_nn") { - std::tie(cpu, vm) = - iss::create_cpu(clim["backend"].as(), clim["gdb-port"].as()); - } else -#endif -#ifdef CORE_TGC_D - if (isa_opt == "tgc_d") { - std::tie(cpu, vm) = - iss::create_cpu(clim["backend"].as(), clim["gdb-port"].as()); - } else -#endif -#ifdef CORE_TGC_D_XRB_MAC - if (isa_opt == "tgc_d_xrb_mac") { - std::tie(cpu, vm) = - iss::create_cpu(clim["backend"].as(), clim["gdb-port"].as()); - } else -#endif -#ifdef CORE_TGC_D_XRB_NN - if (isa_opt == "tgc_d_xrb_nn") { - std::tie(cpu, vm) = - iss::create_cpu(clim["backend"].as(), clim["gdb-port"].as()); - } else -#endif -#ifdef CORE_TGC_E - if (isa_opt == "tgc_e") { - std::tie(cpu, vm) = - iss::create_cpu(clim["backend"].as(), clim["gdb-port"].as()); - } else -#endif - { - LOG(ERR) << "Illegal argument value for '--isa': " << isa_opt << std::endl; + if(isa_opt.size() == 0 || isa_opt == "?") { + auto list = f.get_names(); + std::sort(std::begin(list), std::end(list)); + std::cout << "Available implementations (core|platform|backend):\n - " << util::join(list, "\n - ") << std::endl; + return 0; + } else if(isa_opt.find('|') != std::string::npos) { + std::tie(cpu, vm) = f.create(isa_opt + "|" + clim["backend"].as(), clim["gdb-port"].as()); + } else { + auto base_isa = isa_opt.substr(0, 5); + if(base_isa == "tgc5d" || base_isa == "tgc5e") { + isa_opt += "|mu_p_clic_pmp|" + clim["backend"].as(); + } else { + isa_opt += "|m_p|" + clim["backend"].as(); + } + std::tie(cpu, vm) = f.create(isa_opt, clim["gdb-port"].as()); + } + if(!cpu) { + LOG(ERR) << "Could not create cpu for isa " << isa_opt << " and backend " << clim["backend"].as() << std::endl; return 127; } - if (clim.count("plugin")) { - for (std::string const& opt_val : clim["plugin"].as>()) { - std::string plugin_name=opt_val; - std::string filename{"cycles.txt"}; + if(!vm) { + LOG(ERR) << "Could not create vm for isa " << isa_opt << " and backend " << clim["backend"].as() << std::endl; + return 127; + } + if(clim.count("plugin")) { + for(std::string const& opt_val : clim["plugin"].as>()) { + std::string plugin_name = opt_val; + std::string arg{""}; std::size_t found = opt_val.find('='); - if (found != std::string::npos) { + if(found != std::string::npos) { plugin_name = opt_val.substr(0, found); - filename = opt_val.substr(found + 1, opt_val.size()); + arg = opt_val.substr(found + 1, opt_val.size()); } - if (plugin_name == "ic") { - auto *ic_plugin = new iss::plugin::instruction_count(filename); +#if defined(WITH_PLUGINS) + if(plugin_name == "ic") { + auto* ic_plugin = new iss::plugin::instruction_count(arg); vm->register_plugin(*ic_plugin); plugin_list.push_back(ic_plugin); - } else if (plugin_name == "ce") { - auto *ce_plugin = new iss::plugin::cycle_estimate(filename); + } else if(plugin_name == "ce") { + auto* ce_plugin = new iss::plugin::cycle_estimate(arg); vm->register_plugin(*ce_plugin); plugin_list.push_back(ce_plugin); - } else if (plugin_name == "pctrace") { - auto *plugin = new iss::plugin::cov(filename); - vm->register_plugin(*plugin); - plugin_list.push_back(plugin); - } else { - std::array a{{filename.c_str()}}; + } else +#endif + { +#if !defined(WIN32) + std::vector a{}; + if(arg.length()) + a.push_back({arg.c_str()}); iss::plugin::loader l(plugin_name, {{"initPlugin"}}); auto* plugin = l.call_function("initPlugin", a.size(), a.data()); - if(plugin){ + if(plugin) { vm->register_plugin(*plugin); plugin_list.push_back(plugin); - } else { - LOG(ERR) << "Unknown plugin name: " << plugin_name << ", valid names are 'ce', 'ic'" << std::endl; + } else +#endif + { + LOG(ERR) << "Unknown plugin name: " << plugin_name << ", valid names are 'ce', 'ic'" << std::endl; return 127; } } } } - if (clim.count("disass")) { + if(clim.count("disass")) { vm->setDisassEnabled(true); LOGGER(disass)::reporting_level() = logging::INFO; LOGGER(disass)::print_time() = false; auto file_name = clim["disass"].as(); - if (file_name.length() > 0) { + if(file_name.length() > 0) { LOG_OUTPUT(disass)::stream() = fopen(file_name.c_str(), "w"); LOGGER(disass)::print_severity() = false; } } uint64_t start_address = 0; - if (clim.count("mem")) + if(clim.count("mem")) vm->get_arch()->load_file(clim["mem"].as()); - if (clim.count("elf")) - for (std::string input : clim["elf"].as>()) { + if(clim.count("elf")) + for(std::string input : clim["elf"].as>()) { auto start_addr = vm->get_arch()->load_file(input); - if (start_addr.second) start_address = start_addr.first; + if(start_addr.second) + start_address = start_addr.first; } - for (std::string input : args) { + for(std::string input : args) { auto start_addr = vm->get_arch()->load_file(input); // treat remaining arguments as elf files - if (start_addr.second) start_address = start_addr.first; + if(start_addr.second) + start_address = start_addr.first; } - if (clim.count("reset")) { + if(clim.count("reset")) { auto str = clim["reset"].as(); start_address = str.find("0x") == 0 ? std::stoull(str.substr(2), nullptr, 16) : std::stoull(str, nullptr, 10); } vm->reset(start_address); auto cycles = clim["instructions"].as(); res = vm->start(cycles, dump); - } catch (std::exception &e) { - LOG(ERR) << "Unhandled Exception reached the top of main: " << e.what() << ", application will now exit" - << std::endl; + } catch(std::exception& e) { + LOG(ERR) << "Unhandled Exception reached the top of main: " << e.what() << ", application will now exit" << std::endl; res = 2; } // cleanup to let plugins report of needed - for (auto *p : plugin_list) { + for(auto* p : plugin_list) { delete p; } return res; diff --git a/src/plugin/cycle_estimate.cpp b/src/plugin/cycle_estimate.cpp deleted file mode 100644 index f68d241..0000000 --- a/src/plugin/cycle_estimate.cpp +++ /dev/null @@ -1,118 +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. - * - * Contributors: - * eyck@minres.com - initial API and implementation - ******************************************************************************/ - -#include "iss/plugin/cycle_estimate.h" - -#include -#include -#include -#include -#include "rapidjson/writer.h" -#include "rapidjson/stringbuffer.h" -#include -#include -#include - -using namespace rapidjson; -using namespace std; - -iss::plugin::cycle_estimate::cycle_estimate(string const& config_file_name) -: arch_instr(nullptr) -, config_file_name(config_file_name) -{ -} - -iss::plugin::cycle_estimate::~cycle_estimate() { -} - -bool iss::plugin::cycle_estimate::registration(const char* const version, vm_if& vm) { - arch_instr = vm.get_arch()->get_instrumentation_if(); - if(!arch_instr) return false; - const string core_name = arch_instr->core_type_name(); - if (config_file_name.length() > 0) { - ifstream is(config_file_name); - if (is.is_open()) { - try { - IStreamWrapper isw(is); - Document d; - ParseResult ok = d.ParseStream(isw); - if(ok) { - Value& val = d[core_name.c_str()]; - if(val.IsArray()){ - delays.reserve(val.Size()); - for (auto it = val.Begin(); it != val.End(); ++it) { - auto& name = (*it)["name"]; - auto& size = (*it)["size"]; - auto& delay = (*it)["delay"]; - auto& branch = (*it)["branch"]; - if(delay.IsArray()) { - auto dt = delay[0].Get(); - auto dnt = delay[1].Get(); - delays.push_back(instr_desc{size.Get(), dt, dnt, branch.Get()}); - } else if(delay.Is()) { - auto d = delay.Get(); - delays.push_back(instr_desc{size.Get(), d, d, branch.Get()}); - } else - throw runtime_error("JSON parse error"); - } - } else { - LOG(ERR)<<"plugin cycle_estimate: could not find an entry for "< 1)) - arch_instr->set_curr_instr_cycles(entry.taken); - else if (entry.not_taken > 1) - arch_instr->set_curr_instr_cycles(entry.not_taken); -} diff --git a/src/plugin/pctrace.cpp b/src/plugin/pctrace.cpp deleted file mode 100644 index e178072..0000000 --- a/src/plugin/pctrace.cpp +++ /dev/null @@ -1,133 +0,0 @@ -#include -#include -#include -#include -#include -#include "rapidjson/writer.h" -#include "rapidjson/stringbuffer.h" -#include -#include -#include - -#include - - -using namespace rapidjson; -using namespace std; - -iss::plugin::cov::cov(std::string const &filename) - : instr_if(nullptr) - , filename(filename) -{ - output.open("output.trc"); - jumped = false; - first = true; -} - -iss::plugin::cov::~cov() { - output.close(); -} - -bool iss::plugin::cov::registration(const char *const version, vm_if& vm) { - instr_if = vm.get_arch()->get_instrumentation_if(); - if(!instr_if) return false; - const string core_name = instr_if->core_type_name(); - if (filename.length() > 0) { - ifstream is(filename); - if (is.is_open()) { - try { - IStreamWrapper isw(is); - Document d; - ParseResult ok = d.ParseStream(isw); - if(ok) { - Value& val = d[core_name.c_str()]; - if(val.IsArray()){ - delays.reserve(val.Size()); - for (auto it = val.Begin(); it != val.End(); ++it) { - auto& name = (*it)["name"]; - auto& size = (*it)["size"]; - auto& delay = (*it)["delay"]; - auto& branch = (*it)["branch"]; - if(delay.IsArray()) { - auto dt = delay[0].Get(); - auto dnt = delay[1].Get(); - delays.push_back(instr_desc{size.Get(), dt, dnt, branch.Get()}); - } else if(delay.Is()) { - auto d = delay.Get(); - delays.push_back(instr_desc{size.Get(), d, d, branch.Get()}); - } else - throw runtime_error("JSON parse error"); - - } - } else { - LOG(ERR)<<"plugin cycle_estimate: could not find an entry for "<get_pc()) << "," << delay; -// first = false; -// } -// if(instr_if->get_next_pc()-instr_if->get_pc() != delays[iinfo.instr_id].size/8){ -// //The goal is to keep the output in start-target pairs, so after a jump the target address needs to get written -// //to the output. If the target happens to also be a start, we keep the pairing by adding a 0-delay entry. -// if (jumped) -// output <<"\n" <get_pc()) << "," << 0; -// output <<"\n" << formatPC(instr_if->get_pc()) << "," << delay; -// jumped = true; -// } -// else{ -// if (jumped){ -// output <<"\n" << formatPC(instr_if->get_pc()) << "," << delay; -// jumped = false; -// } -// else if(delay!=1){ -// output <<"\n" << formatPC(instr_if->get_pc()) << "," << delay; -// output <<"\n" << formatPC(instr_if->get_pc()) << "," << 0; -// } -// -// } - -//source code for the full output - auto delay = 0; - auto entry = delays[iinfo.instr_id]; - bool taken = einfo.branch_taken; - if (einfo.branch_taken) - delay = entry.taken; - else - delay = entry.not_taken; - output<get_pc() <<"," << delay << "\n"; -} diff --git a/src/sysc/core_complex.cpp b/src/sysc/core_complex.cpp index 3d29ee8..7b3e601 100644 --- a/src/sysc/core_complex.cpp +++ b/src/sysc/core_complex.cpp @@ -30,30 +30,35 @@ * *******************************************************************************/ -// clang-format off -#include -#include -#include -#include -#include +// clang-format off +#include +#include +#include +#include +#include #include -#include -#include +#include "iss_factory.h" +#ifndef WIN32 +#include +#endif +#include "sc_core_adapter_if.h" #include #include #include #include #include #include +#include #include #include -#include -// clang-format on +// clang-format on #define STR(X) #X -#define CREATE_CORE(CN) \ -if (type == STR(CN)) { std::tie(cpu, vm) = create_core(backend, gdb_port, hart_id); } else +#define CREATE_CORE(CN) \ + if(type == STR(CN)) { \ + std::tie(cpu, vm) = create_core(backend, gdb_port, hart_id); \ + } else #ifdef HAS_SCV #include @@ -68,12 +73,12 @@ using namespace scv_tr; #define GET_PROP_VALUE(P) P.getValue() #endif -#ifdef _MSC_VER -// not #if defined(_WIN32) || defined(_WIN64) because we have strncasecmp in mingw -#define strncasecmp _strnicmp -#define strcasecmp _stricmp -#endif - +#ifdef _MSC_VER +// not #if defined(_WIN32) || defined(_WIN64) because we have strncasecmp in mingw +#define strncasecmp _strnicmp +#define strcasecmp _stricmp +#endif + namespace sysc { namespace tgfs { using namespace std; @@ -83,150 +88,23 @@ using namespace sc_core; namespace { iss::debugger::encoder_decoder encdec; - std::array lvl = {{'U', 'S', 'H', 'M'}}; -} +} // namespace -template -class core_wrapper_t : public PLAT { -public: - using reg_t = typename arch::traits::reg_t; - using phys_addr_t = typename arch::traits::phys_addr_t; - using heart_state_t = typename PLAT::hart_state_type; - core_wrapper_t(core_complex *owner) - : owner(owner) { } - - uint32_t get_mode() { return this->reg.PRIV; } - - inline void set_interrupt_execution(bool v) { this->interrupt_sim = v?1:0; } - - inline bool get_interrupt_execution() { return this->interrupt_sim; } - - heart_state_t &get_state() { return this->state; } - - void notify_phase(iss::arch_if::exec_phase p) override { - if (p == iss::arch_if::ISTART) owner->sync(this->reg.icount); - } - - sync_type needed_sync() const override { return PRE_SYNC; } - - void disass_output(uint64_t pc, const std::string instr) override { - if (!owner->disass_output(pc, instr)) { - std::stringstream s; - s << "[p:" << lvl[this->reg.PRIV] << ";s:0x" << std::hex << std::setfill('0') - << std::setw(sizeof(reg_t) * 2) << (reg_t)this->state.mstatus << std::dec << ";c:" - << this->reg.icount + this->cycle_offset << "]"; - SCCDEBUG(owner->name())<<"disass: " - << "0x" << std::setw(16) << std::right << std::setfill('0') << std::hex << pc << "\t\t" << std::setw(40) - << std::setfill(' ') << std::left << instr << s.str(); - } - }; - - status read_mem(phys_addr_t addr, unsigned length, uint8_t *const data) override { - if (addr.access && access_type::DEBUG) - return owner->read_mem_dbg(addr.val, length, data) ? Ok : Err; - else { - return owner->read_mem(addr.val, length, data, addr.access && access_type::FETCH) ? Ok : Err; - } - } - - status write_mem(phys_addr_t addr, unsigned length, const uint8_t *const data) override { - if (addr.access && access_type::DEBUG) - return owner->write_mem_dbg(addr.val, length, data) ? Ok : Err; - else { - auto res = owner->write_mem(addr.val, length, data) ? Ok : Err; - // clear MTIP on mtimecmp write - if (addr.val == 0x2004000) { - reg_t val; - this->read_csr(arch::mip, val); - if (val & (1ULL << 7)) this->write_csr(arch::mip, val & ~(1ULL << 7)); - } - return res; - } - } - - status read_csr(unsigned addr, reg_t &val) override { -#ifndef CWR_SYSTEMC - if((addr==arch::time || addr==arch::timeh) && owner->mtime_o.get_interface(0)){ - uint64_t time_val; - bool ret = owner->mtime_o->nb_peek(time_val); - if (addr == iss::arch::time) { - val = static_cast(time_val); - } else if (addr == iss::arch::timeh) { - if (sizeof(reg_t) != 4) return iss::Err; - val = static_cast(time_val >> 32); - } - return ret?Ok:Err; -#else - if((addr==arch::time || addr==arch::timeh)){ - uint64_t time_val = owner->mtime_i.read(); - if (addr == iss::arch::time) { - val = static_cast(time_val); - } else if (addr == iss::arch::timeh) { - if (sizeof(reg_t) != 4) return iss::Err; - val = static_cast(time_val >> 32); - } - return Ok; -#endif - } else { - return PLAT::read_csr(addr, val); - } - } - - void wait_until(uint64_t flags) override { - SCCDEBUG(owner->name()) << "Sleeping until interrupt"; - do { - sc_core::wait(wfi_evt); - } while (this->reg.pending_trap == 0); - PLAT::wait_until(flags); - } - - void local_irq(short id, bool value) { - reg_t mask = 0; - switch (id) { - case 16: // SW - mask = 1 << 3; - break; - case 17: // timer - mask = 1 << 7; - break; - case 18: // external - mask = 1 << 11; - break; - default: - /* do nothing*/ - break; - } - if (value) { - this->csr[arch::mip] |= mask; - wfi_evt.notify(); - } else - this->csr[arch::mip] &= ~mask; - this->check_interrupt(); - if(value) - SCCTRACE(owner->name()) << "Triggering interrupt " << id << " Pending trap: " << this->reg.pending_trap; - } - -private: - core_complex *const owner; - sc_event wfi_evt; -}; - -int cmd_sysc(int argc, char *argv[], debugger::out_func of, debugger::data_func df, - debugger::target_adapter_if *tgt_adapter) { - if (argc > 1) { - if (strcasecmp(argv[1], "print_time") == 0) { +int cmd_sysc(int argc, char* argv[], debugger::out_func of, debugger::data_func df, debugger::target_adapter_if* tgt_adapter) { + if(argc > 1) { + if(strcasecmp(argv[1], "print_time") == 0) { std::string t = sc_time_stamp().to_string(); of(t.c_str()); std::array buf; encdec.enc_string(t.c_str(), buf.data(), 63); df(buf.data()); return Ok; - } else if (strcasecmp(argv[1], "break") == 0) { + } else if(strcasecmp(argv[1], "break") == 0) { sc_time t; - if (argc == 4) { + if(argc == 4) { t = scc::parse_from_string(argv[2], argv[3]); - } else if (argc == 3) { + } else if(argc == 3) { t = scc::parse_from_string(argv[2]); } else return Err; @@ -243,15 +121,19 @@ int cmd_sysc(int argc, char *argv[], debugger::out_func of, debugger::data_func } using cpu_ptr = std::unique_ptr; -using vm_ptr= std::unique_ptr; +using vm_ptr = std::unique_ptr; class core_wrapper { public: - core_wrapper(core_complex *owner) : owner(owner) { } + core_wrapper(core_complex* owner) + : owner(owner) {} - void reset(uint64_t addr){vm->reset(addr);} - inline void start(){vm->start();} - inline std::pair load_file(std::string const& name){ return cpu->load_file(name);}; + void reset(uint64_t addr) { vm->reset(addr); } + inline void start(bool dump = false) { vm->start(std::numeric_limits::max(), dump); } + inline std::pair load_file(std::string const& name) { + iss::arch_if* cc = cpu->get_arch_if(); + return cc->load_file(name); + }; std::function get_mode; std::function get_state; @@ -259,91 +141,88 @@ public: std::function set_interrupt_execution; std::function local_irq; - template - std::tuple create_core(std::string const& backend, unsigned gdb_port, uint32_t hart_id){ - auto* lcpu = new core_wrapper_t(owner); - lcpu->set_mhartid(hart_id); - get_mode = [lcpu]() { return lcpu->get_mode(); }; - get_state = [lcpu]() { return lcpu->get_state().mstatus.backing.val; }; - get_interrupt_execution = [lcpu]() { return lcpu->get_interrupt_execution(); }; - set_interrupt_execution = [lcpu](bool b) { return lcpu->set_interrupt_execution(b); }; - local_irq = [lcpu](short s, bool b) { return lcpu->local_irq(s, b); }; - if(backend == "interp") - return {cpu_ptr{lcpu}, vm_ptr{iss::interp::create(static_cast(lcpu), gdb_port)}}; -#ifdef WITH_LLVM - if(backend == "llvm") - return {cpu_ptr{lcpu}, vm_ptr{iss::llvm::create(lcpu, gdb_port)}}; -#endif -#ifdef WITH_TCC - if(backend == "tcc") - s return {cpu_ptr{lcpu}, vm_ptr{iss::tcc::create(lcpu, gdb_port)}}; -#endif - return {nullptr, nullptr}; - } - - void create_cpu(std::string const& type, std::string const& backend, unsigned gdb_port, uint32_t hart_id){ - CREATE_CORE(tgc_c) -#ifdef CORE_TGC_B - CREATE_CORE(tgc_b) -#endif -#ifdef CORE_TGC_D - CREATE_CORE(tgc_d) -#endif -#ifdef CORE_TGC_D_XRB_MAC - CREATE_CORE(tgc_d_xrb_mac) -#endif -#ifdef CORE_TGC_D_XRB_NN - CREATE_CORE(tgc_d_xrb_nn) -#endif - { - LOG(ERR) << "Illegal argument value for core type: " << type << std::endl; + void create_cpu(std::string const& type, std::string const& backend, unsigned gdb_port, uint32_t hart_id) { + auto& f = sysc::iss_factory::instance(); + if(type.size() == 0 || type == "?") { + std::cout << "Available cores: " << util::join(f.get_names(), ", ") << std::endl; + sc_core::sc_stop(); + } else if(type.find('|') != std::string::npos) { + std::tie(cpu, vm) = f.create(type + "|" + backend); + } else { + auto base_isa = type.substr(0, 5); + if(base_isa == "tgc5d" || base_isa == "tgc5e") { + std::tie(cpu, vm) = f.create(type + "|mu_p_clic_pmp|" + backend, gdb_port, owner); + } else { + std::tie(cpu, vm) = f.create(type + "|m_p|" + backend, gdb_port, owner); + } } - auto *srv = debugger::server::get(); - if (srv) tgt_adapter = srv->get_target(); - if (tgt_adapter) - tgt_adapter->add_custom_command( - {"sysc", [this](int argc, char *argv[], debugger::out_func of, - debugger::data_func df) -> int { return cmd_sysc(argc, argv, of, df, tgt_adapter); }, - "SystemC sub-commands: break