Compare commits

..

No commits in common. "main" and "feature/interpreter" have entirely different histories.

132 changed files with 52234 additions and 30321 deletions

View File

@ -1,3 +1,4 @@
---
Language: Cpp
# BasedOnStyle: LLVM
# should be in line with IndentWidth
@ -12,8 +13,8 @@ AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: All
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AllowShortIfStatementsOnASingleLine: true
AllowShortLoopsOnASingleLine: true
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
@ -38,8 +39,8 @@ BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: true
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: true
ColumnLimit: 140
CommentPragmas: '^( IWYU pragma:| @suppress)'
ColumnLimit: 120
CommentPragmas: '^ IWYU pragma:'
ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerIndentWidth: 0
ContinuationIndentWidth: 4
@ -75,13 +76,13 @@ PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 60
PointerAlignment: Left
PointerAlignment: Right
ReflowComments: true
SortIncludes: true
SpaceAfterCStyleCast: false
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeParens: Never
SpaceBeforeParens: ControlStatements
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: false

5
.gitignore vendored
View File

@ -1,6 +1,5 @@
.DS_Store
/*.il
/.settings
/avr-instr.html
/blink.S
/flash.*
@ -15,6 +14,7 @@
/*.ods
/build*/
/*.logs
language.settings.xml
/*.gtkw
/Debug wo LLVM/
/*.txdb
@ -30,5 +30,4 @@
/.gdbinit
/*.out
/dump.json
/*.yaml
/*.json
/src-gen/

View File

@ -23,5 +23,6 @@
<nature>org.eclipse.cdt.core.ccnature</nature>
<nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
<nature>org.eclipse.linuxtools.tmf.project.nature</nature>
</natures>
</projectDescription>

View File

@ -0,0 +1,73 @@
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\\")"}

View File

@ -0,0 +1,13 @@
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

View File

@ -0,0 +1,37 @@
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

View File

@ -1,263 +1,147 @@
cmake_minimum_required(VERSION 3.18)
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
cmake_minimum_required(VERSION 3.12)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/../cmake) # main (top) cmake dir
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake) # project specific cmake dir
# ##############################################################################
#
# ##############################################################################
project(dbt-rise-tgc VERSION 1.0.0)
# CMake useful variables
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin")
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib")
include(GNUInstallDirs)
include(flink)
# Set the name of your project here
project("riscv")
find_package(elfio QUIET)
find_package(jsoncpp)
find_package(Boost COMPONENTS coroutine REQUIRED)
include(Common)
conan_basic_setup()
find_package(Boost COMPONENTS program_options system thread filesystem REQUIRED)
# This sets the include directory for the reference project. This is the -I flag in gcc.
include_directories(
${PROJECT_SOURCE_DIR}/incl
${SOFTFLOAT_INCLUDE_DIRS}
${LLVM_INCLUDE_DIRS}
)
add_dependent_subproject(dbt-core)
include_directories(
${PROJECT_SOURCE_DIR}/incl
${PROJECT_SOURCE_DIR}/../external/elfio
${PROJECT_SOURCE_DIR}/../external/libGIS
${Boost_INCLUDE_DIRS}
)
# Mac needed variables (adapt for your needs - http://www.cmake.org/Wiki/CMake_RPATH_handling#Mac_OS_X_and_the_RPATH)
set(CMAKE_MACOSX_RPATH ON)
set(CMAKE_SKIP_BUILD_RPATH FALSE)
set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE)
set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
add_subdirectory(softfloat)
set(LIB_SOURCES
src/iss/plugin/instruction_count.cpp
src/iss/arch/tgc5c.cpp
src/vm/interp/vm_tgc5c.cpp
src/vm/fp_functions.cpp
src/iss/semihosting/semihosting.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})
FILE(GLOB RiscVSCHeaders ${CMAKE_CURRENT_SOURCE_DIR}/incl/sysc/*.h ${CMAKE_CURRENT_SOURCE_DIR}/incl/sysc/*/*.h)
set(LIB_HEADERS ${RiscVSCHeaders} )
set(LIB_SOURCES
#src/iss/rv32gc.cpp
src/iss/rv32imac.cpp
#src/iss/rv64i.cpp
#src/iss/rv64gc.cpp
src/iss/mnrv32.cpp
src/vm/llvm/fp_functions.cpp
src/vm/llvm/vm_mnrv32.cpp
#src/vm/llvm/vm_rv32gc.cpp
#src/vm/llvm/vm_rv32imac.cpp
#src/vm/llvm/vm_rv64i.cpp
#src/vm/llvm/vm_rv64gc.cpp
src/vm/tcc/vm_mnrv32.cpp
src/vm/interp/vm_mnrv32.cpp
src/plugin/instruction_count.cpp
src/plugin/cycle_estimate.cpp)
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 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 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 two variables in order not to repeat ourselves.
set(LIBRARY_NAME riscv)
# Define the library
add_library(${PROJECT_NAME} SHARED ${LIB_SOURCES})
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
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 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}
FRAMEWORK FALSE
)
install(TARGETS ${PROJECT_NAME} COMPONENT ${PROJECT_NAME}
EXPORT ${PROJECT_NAME}Targets # for downstream dependencies
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} # static lib
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} # binaries
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} # shared lib
FRAMEWORK DESTINATION ${CMAKE_INSTALL_LIBDIR} # for mac
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME} # headers for mac (note the different component -> different package)
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} # headers
)
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/incl/iss COMPONENT ${PROJECT_NAME}
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} # target directory
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)
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()
# 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()
target_link_libraries(${PROJECT_NAME} PUBLIC ${BOOST_program_options_LIBRARY})
endif()
target_link_libraries(${PROJECT_NAME} PUBLIC ${CMAKE_DL_LIBS})
if(Tcmalloc_FOUND)
target_link_libraries(${PROJECT_NAME} PUBLIC ${Tcmalloc_LIBRARIES})
endif(Tcmalloc_FOUND)
install(TARGETS tgc-sim
EXPORT ${PROJECT_NAME}Targets # for downstream dependencies
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} # static lib
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} # binaries
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} # shared lib
FRAMEWORK DESTINATION ${CMAKE_INSTALL_LIBDIR} # for mac
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()
# ##############################################################################
#
# ##############################################################################
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)
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-sysc)
# if(WITH_LLVM)
# target_link_libraries(${PROJECT_NAME} PUBLIC ${llvm_libs})
# endif()
set(LIB_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/src/sysc/core_complex.h)
set_target_properties(${PROJECT_NAME} PROPERTIES
VERSION ${PROJECT_VERSION}
add_library(${LIBRARY_NAME} ${LIB_SOURCES})
SET(${LIBRARY_NAME} -Wl,-whole-archive -l${LIBRARY_NAME} -Wl,-no-whole-archive)
target_link_libraries(${LIBRARY_NAME} softfloat dbt-core scc-util)
set_target_properties(${LIBRARY_NAME} PROPERTIES
VERSION ${VERSION} # ${VERSION} was defined in the main CMakeLists.
FRAMEWORK FALSE
PUBLIC_HEADER "${LIB_HEADERS}" # specify the public headers
)
install(TARGETS ${PROJECT_NAME} COMPONENT ${PROJECT_NAME}
EXPORT ${PROJECT_NAME}Targets # for downstream dependencies
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} # static lib
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} # binaries
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} # shared lib
FRAMEWORK DESTINATION ${CMAKE_INSTALL_LIBDIR} # for mac
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/sysc # headers for mac (note the different component -> different package)
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} # headers
if(SystemC_FOUND)
set(SC_LIBRARY_NAME riscv_sc)
add_library(${SC_LIBRARY_NAME} src/sysc/core_complex.cpp)
add_definitions(-DWITH_SYSTEMC)
include_directories(${SystemC_INCLUDE_DIRS})
include_directories(${CCI_INCLUDE_DIRS})
if(SCV_FOUND)
add_definitions(-DWITH_SCV)
include_directories(${SCV_INCLUDE_DIRS})
endif()
target_link_libraries(${SC_LIBRARY_NAME} ${LIBRARY_NAME})
target_link_libraries(${SC_LIBRARY_NAME} dbt-core)
target_link_libraries(${SC_LIBRARY_NAME} softfloat)
target_link_libraries(${SC_LIBRARY_NAME} scc)
target_link_libraries(${SC_LIBRARY_NAME} external)
target_link_libraries(${SC_LIBRARY_NAME} ${llvm_libs})
target_link_libraries(${SC_LIBRARY_NAME} ${Boost_LIBRARIES} )
set_target_properties(${SC_LIBRARY_NAME} PROPERTIES
VERSION ${VERSION} # ${VERSION} was defined in the main CMakeLists.
FRAMEWORK FALSE
PUBLIC_HEADER "${LIB_HEADERS}" # specify the public headers
)
endif()
project("riscv-sim")
# This is a make target, so you can do a "make riscv-sc"
set(APPLICATION_NAME riscv-sim)
add_executable(${APPLICATION_NAME} src/main.cpp)
# Links the target exe against the libraries
target_link_libraries(${APPLICATION_NAME} ${LIBRARY_NAME})
target_link_libraries(${APPLICATION_NAME} jsoncpp)
target_link_libraries(${APPLICATION_NAME} dbt-core)
target_link_libraries(${APPLICATION_NAME} external)
target_link_libraries(${APPLICATION_NAME} ${llvm_libs})
target_link_libraries(${APPLICATION_NAME} ${Boost_LIBRARIES} )
if (Tcmalloc_FOUND)
target_link_libraries(${APPLICATION_NAME} ${Tcmalloc_LIBRARIES})
endif(Tcmalloc_FOUND)
# Says how and where to install software
# Targets:
# * <prefix>/lib/<libraries>
# * header location after install: <prefix>/include/<project>/*.h
# * headers can be included by C++ code `#<project>/Bar.hpp>`
install(TARGETS ${LIBRARY_NAME} ${APPLICATION_NAME}
EXPORT ${PROJECT_NAME}Targets # for downstream dependencies
ARCHIVE DESTINATION lib COMPONENT libs # static lib
RUNTIME DESTINATION bin COMPONENT libs # binaries
LIBRARY DESTINATION lib COMPONENT libs # shared lib
FRAMEWORK DESTINATION bin COMPONENT libs # for mac
PUBLIC_HEADER DESTINATION incl/${PROJECT_NAME} COMPONENT devel # headers for mac (note the different component -> different package)
INCLUDES DESTINATION incl # headers
)
#
# SYSTEM PACKAGING (RPM, TGZ, ...)
# _____________________________________________________________________________
#include(CPackConfig)
#
# CMAKE PACKAGING (for other CMake projects to use this one easily)
# _____________________________________________________________________________
#include(PackageConfigurator)

119
CMakeLists.txt.orig Normal file
View File

@ -0,0 +1,119 @@
cmake_minimum_required(VERSION 3.3)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake ${CMAKE_CURRENT_SOURCE_DIR}/sc-components/cmake)
set(ENABLE_SCV TRUE CACHE BOOL "Enable use of SCV")
set(ENABLE_SHARED TRUE CACHE BOOL "Build shared libraries")
include(GitFunctions)
get_branch_from_git()
# if we are not on master or develop set the submodules to develop
IF(NOT ${GIT_BRANCH} MATCHES "master")
IF(NOT ${GIT_BRANCH} MATCHES "develop")
message(STATUS "main branch is '${GIT_BRANCH}', setting submodules to 'develop'")
set(GIT_BRANCH develop)
endif()
endif()
### set the directory names of the submodules
set(GIT_SUBMODULES elfio libGIS sc-components dbt-core)
set(GIT_SUBMODULE_DIR_sc-components .)
set(GIT_SUBMODULE_DIR_dbt-core .)
### set each submodules's commit or tag that is to be checked out
### (leave empty if you want master)
#set(GIT_SUBMODULE_VERSION_sc-comp 3af6b9836589b082c19d9131c5d0b7afa8ddd7cd)
set(GIT_SUBMODULE_BRANCH_sc-components ${GIT_BRANCH})
set(GIT_SUBMODULE_BRANCH_dbt-core ${GIT_BRANCH})
include(GNUInstallDirs)
include(Submodules)
include(Conan)
#enable_testing()
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG("-march=native" COMPILER_SUPPORTS_MARCH_NATIVE)
if(COMPILER_SUPPORTS_MARCH_NATIVE)
if("${CMAKE_BUILD_TYPE}" STREQUAL "")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native")
elseif(NOT(${CMAKE_BUILD_TYPE} STREQUAL "RelWithDebInfo"))
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native")
endif()
endif()
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
set(warnings "-Wall -Wextra -Werror")
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_GLIBCXX_USE_CXX11_ABI=0")
set(CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG")
set(CMAKE_C_FLAGS_RELEASE "-O3 -DNDEBUG")
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
set(warnings "/W4 /WX /EHsc")
endif()
setup_conan()
# This line finds the boost lib and headers.
set(Boost_NO_BOOST_CMAKE ON) # Don't do a find_package in config mode before searching for a regular boost install.
find_package(Boost COMPONENTS program_options system thread filesystem REQUIRED)
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)
find_package(Threads)
find_package(Tcmalloc)
find_package(ZLIB)
find_package(SystemC)
if(SystemC_FOUND)
message(STATUS "SystemC headers at ${SystemC_INCLUDE_DIRS}")
message(STATUS "SystemC library at ${SystemC_LIBRARY_DIRS}")
if(SCV_FOUND)
message(STATUS "SCV headers at ${SCV_INCLUDE_DIRS}")
message(STATUS "SCV library at ${SCV_LIBRARY_DIRS}")
endif(SCV_FOUND)
if(CCI_FOUND)
message(STATUS "CCI headers at ${CCI_INCLUDE_DIRS}")
message(STATUS "CCI library at ${CCI_LIBRARY_DIRS}")
endif()
endif(SystemC_FOUND)
set(PROJECT_3PARTY_DIRS external)
include(clang-format)
set(ENABLE_CLANG_TIDY OFF CACHE BOOL "Add clang-tidy automatically to builds")
if (ENABLE_CLANG_TIDY)
find_program (CLANG_TIDY_EXE NAMES "clang-tidy" PATHS /usr/local/opt/llvm/bin )
if (CLANG_TIDY_EXE)
message(STATUS "clang-tidy found: ${CLANG_TIDY_EXE}")
set(CLANG_TIDY_CHECKS "-*,modernize-*")
set(CMAKE_CXX_CLANG_TIDY "${CLANG_TIDY_EXE};-checks=${CLANG_TIDY_CHECKS};-header-filter='${CMAKE_SOURCE_DIR}/*';-fix"
CACHE STRING "" FORCE)
else()
message(AUTHOR_WARNING "clang-tidy not found!")
set(CMAKE_CXX_CLANG_TIDY "" CACHE STRING "" FORCE) # delete it
endif()
endif()
# Set the version number of your project here (format is MAJOR.MINOR.PATCHLEVEL - e.g. 1.0.0)
set(VERSION_MAJOR "1")
set(VERSION_MINOR "0")
set(VERSION_PATCH "0")
set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH})
add_subdirectory(external)
add_subdirectory(dbt-core)
add_subdirectory(sc-components)
add_subdirectory(softfloat)
GET_DIRECTORY_PROPERTY(SOFTFLOAT_INCLUDE_DIRS DIRECTORY softfloat DEFINITION SOFTFLOAT_INCLUDE_DIRS)
add_subdirectory(riscv)
add_subdirectory(platform)
message(STATUS "Build Type: ${CMAKE_BUILD_TYPE}")

View File

@ -1,16 +1,18 @@
# DBT-RISE-TGFS
Core of an instruction set simulator based on DBT-RISE implementing Minres The Good Folks Series cores. The project is hosted at https://git.minres.com/DBT-RISE/DBT-RISE-TGFS .
# DBT-RISE-RISCV
Core of an instruction set simulator based on DBT-RISE implementing the RISC-V ISA. The project is hosted at https://git.minres.com/DBT-RISE/DBT-RISE-RISCV .
This repo contains only the code of the RISC-V ISS and can only be used with the DBT_RISE. A complete VP using this ISS can be found at https://git.minres.com/VP/Ecosystem-VP ~~which models SiFives FE310 controlling a brushless DC (BLDC) motor~~.
This repo contains only the code of the RISC-V ISS and can only be used with the DBT_RISE. A complete VP using this ISS can be found at https://git.minres.com/VP/RISCV-VP which models SiFives FE310 controlling a brushless DC (BLDC) motor.
This library provide the infrastructure to build RISC-V ISS. Currently part of the library are the following implementations adhering to version 2.2 of the 'The RISC-V Instruction Set Manual Volume I: User-Level ISA':
* RV32I (TGF-B)
* RV32MIC (TGF-C)
* RV32IMAC
* RV32GC
* RC64I
* RV64GC
All pass the respective compliance tests. Along with those ISA implementations there is a wrapper (riscv_hart_m_p.h) implementing the Machine privileged mode as of privileged spec 1.10. The main.cpp in src allows to build a stand-alone ISS when integrated into a top-level project. For further information please have a look at [https://git.minres.com/VP/RISCV-VP](https://git.minres.com/VP/RISCV-VP).
All pass the respective compliance tests. Along with those ISA implementations there is a wrapper implementing the M/S/U modes inlcuding virtual memory management and CSRs as of privileged spec 1.10. The main.cpp in src allows to build a standalone ISS when integrated into a top-level project. For further information please have a look at [https://git.minres.com/VP/RISCV-VP](https://git.minres.com/VP/RISCV-VP).
Last but not least an SystemC wrapper is provided which allows easy integration into SystemC based virtual platforms.
Since DBT-RISE uses a generative approach other needed combinations or custom extension can be generated. For further information please contact [info@minres.com](mailto:info@minres.com).
Since DBT-RISE uses a generative approch other needed combinations or custom extension can be generated. For further information please contact [info@minres.com](mailto:info@minres.com).

View File

@ -1,35 +0,0 @@
# 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()

View File

@ -1 +0,0 @@
/*.yaml

View File

@ -1,624 +0,0 @@
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
RVM:
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

View File

@ -1,650 +0,0 @@
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

View File

@ -1,3 +0,0 @@
/results
/cwr
/*.xml

View File

@ -1,43 +0,0 @@
# 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 <your SNPS PA installation>
setenv SNPSLMD_LICENSE_FILE <your SNPS PA 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
```

View File

@ -1,30 +0,0 @@
namespace eval Specification {
proc buildproc { args } {
global env
variable installDir
variable compiler
variable compiler [::scsh::get_backend_compiler]
# set target $machine
set target [::scsh::machine]
set linkerOptions ""
set preprocessorOptions ""
set libversion $compiler
switch -exact -- $target {
"linux" {
set install_dir $::env(TGFS_INSTALL_ROOT)
set incldir "${install_dir}/include"
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 -lscc-sysc"]
}
default {
puts stderr "ERROR: \"$target\" is not supported, [::scsh::version]"
return
}
}
::scsh::cwr_append_ipsimbld_opts preprocessor "$preprocessorOptions"
::scsh::cwr_append_ipsimbld_opts linker "$linkerOptions"
}
::scsh::add_build_callback [namespace current]::buildproc
}

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

View File

@ -1,4 +0,0 @@
#include "sysc/core_complex.h"
void modules() { sysc::tgfs::core_complex i_core_complex("core_complex"); }

View File

@ -1,50 +0,0 @@
#############################################################################
#
#############################################################################
proc getScriptDirectory {} {
set dispScriptFile [file normalize [info script]]
set scriptFolder [file dirname $dispScriptFile]
return $scriptFolder
}
set hardware /HARDWARE/HW/HW
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_"
set model_postfix ""
::pct::new_project
::pct::open_library TLM2_PL
::pct::clear_systemc_defines
::pct::clear_systemc_include_path
::pct::add_to_systemc_include_path $::env(TGFS_INSTALL_ROOT)/include
::pct::set_import_protocol_generation_flag false
::pct::set_update_existing_encaps_flag true
::pct::set_dynamic_port_arrays_flag true
::pct::set_import_scml_properties_flag true
::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}
foreach clock ${clocks} {
::pct::set_block_port_protocol --set-category SYSTEM_LIBRARY:$block/${clock} SYSTEM_LIBRARY:CLOCK
}
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
# Set compile settings and look
set block SYSTEM_LIBRARY:${top_design_name}
::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} ${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

View File

@ -1,71 +0,0 @@
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/report.h>} {::scc::init_logging(::scc::LogConfig().logLevel(::scc::log::INFO).coloredOutput(false).logAsync(false));} {} {} {}}
::pct::set_main_configuration Debug {{#include <scc/report.h>} {::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

View File

@ -1,2 +1 @@
/src-gen/
/CoreDSL-Instruction-Set-Description

View File

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

309
gen_input/RV32I.core_desc Normal file
View File

@ -0,0 +1,309 @@
import "RISCVBase.core_desc"
InsructionSet RV32I extends RISCVBase{
instructions {
LUI{
encoding: imm[31:12]s | rd[4:0] | b0110111;
args_disass: "{name(rd)}, {imm:#05x}";
if(rd!=0) X[rd] <= imm;
}
AUIPC{
encoding: imm[31:12]s | rd[4:0] | b0010111;
args_disass: "{name(rd)}, {imm:#08x}";
if(rd!=0) X[rd] <= PC's+imm;
}
JAL(no_cont){
encoding: imm[20:20]s | imm[10:1]s | imm[11:11]s | imm[19:12]s | rd[4:0] | b1101111;
args_disass: "{name(rd)}, {imm:#0x}";
if(rd!=0) X[rd] <= PC+4;
PC<=PC's+imm;
}
JALR(no_cont){
encoding: imm[11:0]s | rs1[4:0] | b000 | rd[4:0] | b1100111;
args_disass: "{name(rd)}, {name(rs1)}, {imm:#0x}";
val new_pc[XLEN] <= X[rs1]'s+ imm;
val align[XLEN] <= new_pc & 0x2;
if(align != 0){
raise(0, 0);
} else {
if(rd!=0) X[rd] <= PC+4;
PC<=new_pc & ~0x1;
}
}
BEQ(no_cont,cond){
encoding: imm[12:12]s |imm[10:5]s | rs2[4:0] | rs1[4:0] | b000 | imm[4:1]s | imm[11:11]s | b1100011;
args_disass:"{name(rs1)}, {name(rs2)}, {imm:#0x}";
PC<=choose(X[rs1]==X[rs2], PC's+imm, PC+4);
}
BNE(no_cont,cond){
encoding: imm[12:12]s |imm[10:5]s | rs2[4:0] | rs1[4:0] | b001 | imm[4:1]s | imm[11:11]s | b1100011;
args_disass:"{name(rs1)}, {name(rs2)}, {imm:#0x}";
PC<=choose(X[rs1]!=X[rs2], PC's+imm, PC+4);
}
BLT(no_cont,cond){
encoding: imm[12:12]s |imm[10:5]s | rs2[4:0] | rs1[4:0] | b100 | imm[4:1]s | imm[11:11]s | b1100011;
args_disass:"{name(rs1)}, {name(rs2)}, {imm:#0x}";
PC<=choose(X[rs1]s<X[rs2]s, PC's+imm, PC+4);
}
BGE(no_cont,cond) {
encoding: imm[12:12]s |imm[10:5]s | rs2[4:0] | rs1[4:0] | b101 | imm[4:1]s | imm[11:11]s | b1100011;
args_disass:"{name(rs1)}, {name(rs2)}, {imm:#0x}";
PC<=choose(X[rs1]s>=X[rs2]s, PC's+imm, PC+4);
}
BLTU(no_cont,cond) {
encoding: imm[12:12]s |imm[10:5]s | rs2[4:0] | rs1[4:0] | b110 | imm[4:1]s | imm[11:11]s | b1100011;
args_disass:"{name(rs1)}, {name(rs2)}, {imm:#0x}";
PC<=choose(X[rs1]<X[rs2],PC's+imm, PC+4);
}
BGEU(no_cont,cond) {
encoding: imm[12:12]s |imm[10:5]s | rs2[4:0] | rs1[4:0] | b111 | imm[4:1]s | imm[11:11]s | b1100011;
args_disass:"{name(rs1)}, {name(rs2)}, {imm:#0x}";
PC<=choose(X[rs1]>=X[rs2], PC's+imm, PC+4);
}
LB {
encoding: imm[11:0]s | rs1[4:0] | b000 | rd[4:0] | b0000011;
args_disass:"{name(rd)}, {imm}({name(rs1)})";
val offs[XLEN] <= X[rs1]'s+imm;
if(rd!=0) X[rd]<=sext(MEM[offs]);
}
LH {
encoding: imm[11:0]s | rs1[4:0] | b001 | rd[4:0] | b0000011;
args_disass:"{name(rd)}, {imm}({name(rs1)})";
val offs[XLEN] <= X[rs1]'s+imm;
if(rd!=0) X[rd]<=sext(MEM[offs]{16});
}
LW {
encoding: imm[11:0]s | rs1[4:0] | b010 | rd[4:0] | b0000011;
args_disass:"{name(rd)}, {imm}({name(rs1)})";
val offs[XLEN] <= X[rs1]'s+imm;
if(rd!=0) X[rd]<=sext(MEM[offs]{32});
}
LBU {
encoding: imm[11:0]s | rs1[4:0] | b100 | rd[4:0] | b0000011;
args_disass:"{name(rd)}, {imm}({name(rs1)})";
val offs[XLEN] <= X[rs1]'s+imm;
if(rd!=0) X[rd]<=zext(MEM[offs]);
}
LHU {
encoding: imm[11:0]s | rs1[4:0] | b101 | rd[4:0] | b0000011;
args_disass:"{name(rd)}, {imm}({name(rs1)})";
val offs[XLEN] <= X[rs1]'s+imm;
if(rd!=0) X[rd]<=zext(MEM[offs]{16});
}
SB {
encoding: imm[11:5]s | rs2[4:0] | rs1[4:0] | b000 | imm[4:0]s | b0100011;
args_disass:"{name(rs2)}, {imm}({name(rs1)})";
val offs[XLEN] <= X[rs1]'s + imm;
MEM[offs] <= X[rs2];
}
SH {
encoding: imm[11:5]s | rs2[4:0] | rs1[4:0] | b001 | imm[4:0]s | b0100011;
args_disass:"{name(rs2)}, {imm}({name(rs1)})";
val offs[XLEN] <= X[rs1]'s + imm;
MEM[offs]{16} <= X[rs2];
}
SW {
encoding: imm[11:5]s | rs2[4:0] | rs1[4:0] | b010 | imm[4:0]s | b0100011;
args_disass:"{name(rs2)}, {imm}({name(rs1)})";
val offs[XLEN] <= X[rs1]'s + imm;
MEM[offs]{32} <= X[rs2];
}
ADDI {
encoding: imm[11:0]s | rs1[4:0] | b000 | rd[4:0] | b0010011;
args_disass:"{name(rd)}, {name(rs1)}, {imm}";
if(rd != 0) X[rd] <= X[rs1]'s + imm;
}
SLTI {
encoding: imm[11:0]s | rs1[4:0] | b010 | rd[4:0] | b0010011;
args_disass:"{name(rd)}, {name(rs1)}, {imm}";
if (rd != 0) X[rd] <= choose(X[rs1]s < imm's, 1, 0);
}
SLTIU {
encoding: imm[11:0]s | rs1[4:0] | b011 | rd[4:0] | b0010011;
args_disass:"{name(rd)}, {name(rs1)}, {imm}";
val full_imm[XLEN] <= imm's;
if (rd != 0) X[rd] <= choose(X[rs1]'u < full_imm'u, 1, 0);
}
XORI {
encoding: imm[11:0]s | rs1[4:0] | b100 | rd[4:0] | b0010011;
args_disass:"{name(rd)}, {name(rs1)}, {imm}";
if(rd != 0) X[rd] <= X[rs1]s ^ imm;
}
ORI {
encoding: imm[11:0]s | rs1[4:0] | b110 | rd[4:0] | b0010011;
args_disass:"{name(rd)}, {name(rs1)}, {imm}";
if(rd != 0) X[rd] <= X[rs1]s | imm;
}
ANDI {
encoding: imm[11:0]s | rs1[4:0] | b111 | rd[4:0] | b0010011;
args_disass:"{name(rd)}, {name(rs1)}, {imm}";
if(rd != 0) X[rd] <= X[rs1]s & imm;
}
SLLI {
encoding: b0000000 | shamt[4:0] | rs1[4:0] | b001 | rd[4:0] | b0010011;
args_disass:"{name(rd)}, {name(rs1)}, {shamt}";
if(shamt > 31){
raise(0,0);
} else {
if(rd != 0) X[rd] <= shll(X[rs1], shamt);
}
}
SRLI {
encoding: b0000000 | shamt[4:0] | rs1[4:0] | b101 | rd[4:0] | b0010011;
args_disass:"{name(rd)}, {name(rs1)}, {shamt}";
if(shamt > 31){
raise(0,0);
} else {
if(rd != 0) X[rd] <= shrl(X[rs1], shamt);
}
}
SRAI {
encoding: b0100000 | shamt[4:0] | rs1[4:0] | b101 | rd[4:0] | b0010011;
args_disass:"{name(rd)}, {name(rs1)}, {shamt}";
if(shamt > 31){
raise(0,0);
} else {
if(rd != 0) X[rd] <= shra(X[rs1], shamt);
}
}
ADD {
encoding: b0000000 | rs2[4:0] | rs1[4:0] | b000 | rd[4:0] | b0110011;
args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}";
if(rd != 0) X[rd] <= X[rs1] + X[rs2];
}
SUB {
encoding: b0100000 | rs2[4:0] | rs1[4:0] | b000 | rd[4:0] | b0110011;
args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}";
if(rd != 0) X[rd] <= X[rs1] - X[rs2];
}
SLL {
encoding: b0000000 | rs2[4:0] | rs1[4:0] | b001 | rd[4:0] | b0110011;
args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}";
if(rd != 0) X[rd] <= shll(X[rs1], X[rs2]&(XLEN-1));
}
SLT {
encoding: b0000000 | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b0110011;
args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}";
if (rd != 0) X[rd] <= choose(X[rs1]s < X[rs2]s, 1, 0);
}
SLTU {
encoding: b0000000 | rs2[4:0] | rs1[4:0] | b011 | rd[4:0] | b0110011;
args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}";
if (rd != 0) X[rd] <= choose(zext(X[rs1]) < zext(X[rs2]), 1, 0);
}
XOR {
encoding: b0000000 | rs2[4:0] | rs1[4:0] | b100 | rd[4:0] | b0110011;
args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}";
if(rd != 0) X[rd] <= X[rs1] ^ X[rs2];
}
SRL {
encoding: b0000000 | rs2[4:0] | rs1[4:0] | b101 | rd[4:0] | b0110011;
args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}";
if(rd != 0) X[rd] <= shrl(X[rs1], X[rs2]&(XLEN-1));
}
SRA {
encoding: b0100000 | rs2[4:0] | rs1[4:0] | b101 | rd[4:0] | b0110011;
args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}";
if(rd != 0) X[rd] <= shra(X[rs1], X[rs2]&(XLEN-1));
}
OR {
encoding: b0000000 | rs2[4:0] | rs1[4:0] | b110 | rd[4:0] | b0110011;
args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}";
if(rd != 0) X[rd] <= X[rs1] | X[rs2];
}
AND {
encoding: b0000000 | rs2[4:0] | rs1[4:0] | b111 | rd[4:0] | b0110011;
args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}";
if(rd != 0) X[rd] <= X[rs1] & X[rs2];
}
FENCE {
encoding: b0000 | pred[3:0] | succ[3:0] | rs1[4:0] | b000 | rd[4:0] | b0001111;
FENCE[fence] <= pred<<4 | succ;
}
FENCE_I(flush) {
encoding: imm[11:0] | rs1[4:0] | b001 | rd[4:0] | b0001111 ;
FENCE[fencei] <= imm;
}
ECALL(no_cont) {
encoding: b000000000000 | b00000 | b000 | b00000 | b1110011;
raise(0, 11);
}
EBREAK(no_cont) {
encoding: b000000000001 | b00000 | b000 | b00000 | b1110011;
raise(0, 3);
}
URET(no_cont) {
encoding: b0000000 | b00010 | b00000 | b000 | b00000 | b1110011;
leave(0);
}
SRET(no_cont) {
encoding: b0001000 | b00010 | b00000 | b000 | b00000 | b1110011;
leave(1);
}
MRET(no_cont) {
encoding: b0011000 | b00010 | b00000 | b000 | b00000 | b1110011;
leave(3);
}
WFI {
encoding: b0001000 | b00101 | b00000 | b000 | b00000 | b1110011;
wait(1);
}
SFENCE.VMA {
encoding: b0001001 | rs2[4:0] | rs1[4:0] | b000 | b00000 | b1110011;
FENCE[fencevmal] <= rs1;
FENCE[fencevmau] <= rs2;
}
CSRRW {
encoding: csr[11:0] | rs1[4:0] | b001 | rd[4:0] | b1110011;
args_disass:"{name(rd)}, {csr}, {name(rs1)}";
val rs_val[XLEN] <= X[rs1];
if(rd!=0){
val csr_val[XLEN] <= CSR[csr];
CSR[csr] <= rs_val;
// make sure Xrd is updated once CSR write succeeds
X[rd] <= csr_val;
} else {
CSR[csr] <= rs_val;
}
}
CSRRS {
encoding: csr[11:0] | rs1[4:0] | b010 | rd[4:0] | b1110011;
args_disass:"{name(rd)}, {csr}, {name(rs1)}";
val xrd[XLEN] <= CSR[csr];
val xrs1[XLEN] <= X[rs1];
if(rd!=0) X[rd] <= xrd;
if(rs1!=0) CSR[csr] <= xrd | xrs1;
}
CSRRC {
encoding: csr[11:0] | rs1[4:0] | b011 | rd[4:0] | b1110011;
args_disass:"{name(rd)}, {csr}, {name(rs1)}";
val xrd[XLEN] <= CSR[csr];
val xrs1[XLEN] <= X[rs1];
if(rd!=0) X[rd] <= xrd;
if(rs1!=0) CSR[csr] <= xrd & ~xrs1;
}
CSRRWI {
encoding: csr[11:0] | zimm[4:0] | b101 | rd[4:0] | b1110011;
args_disass:"{name(rd)}, {csr}, {zimm:#0x}";
if(rd!=0) X[rd] <= CSR[csr];
CSR[csr] <= zext(zimm);
}
CSRRSI {
encoding: csr[11:0] | zimm[4:0] | b110 | rd[4:0] | b1110011;
args_disass:"{name(rd)}, {csr}, {zimm:#0x}";
val res[XLEN] <= CSR[csr];
if(zimm!=0) CSR[csr] <= res | zext(zimm);
// make sure rd is written after csr write succeeds
if(rd!=0) X[rd] <= res;
}
CSRRCI {
encoding: csr[11:0] | zimm[4:0] | b111 | rd[4:0] | b1110011;
args_disass:"{name(rd)}, {csr}, {zimm:#0x}";
val res[XLEN] <= CSR[csr];
if(rd!=0) X[rd] <= res;
if(zimm!=0) CSR[csr] <= res & ~zext(zimm, XLEN);
}
}
}

116
gen_input/RV64I.core_desc Normal file
View File

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

210
gen_input/RVA.core_desc Normal file
View File

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

367
gen_input/RVC.core_desc Normal file
View File

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

360
gen_input/RVD.core_desc Normal file
View File

@ -0,0 +1,360 @@
import "RISCVBase.core_desc"
InsructionSet RV32D extends RISCVBase{
constants {
FLEN, FFLAG_MASK := 0x1f
}
registers {
[31:0] F[FLEN], FCSR[32]
}
instructions{
FLD {
encoding: imm[11:0]s | rs1[4:0] | b011 | rd[4:0] | b0000111;
args_disass:"f{rd}, {imm}({name(rs1)})";
val offs[XLEN] <= X[rs1]'s + imm;
val res[64] <= MEM[offs]{64};
if(FLEN==64)
F[rd] <= res;
else { // NaN boxing
val upper[FLEN] <= -1;
F[rd] <= (upper<<64) | res;
}
}
FSD {
encoding: imm[11:5]s | rs2[4:0] | rs1[4:0] | b011 | imm[4:0]s | b0100111;
args_disass:"f{rs2}, {imm}({name(rs1)})";
val offs[XLEN] <= X[rs1]'s + imm;
MEM[offs]{64}<=F[rs2]{64};
}
FMADD.D {
encoding: rs3[4:0] | b01 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1000011;
args_disass:"{name(rd)}, f{rs1}, f{rs2}, f{rs3}";
//F[rd]f<= F[rs1]f * F[rs2]f + F[rs3]f;
val res[64] <= fdispatch_fmadd_d(F[rs1]{64}, F[rs2]{64}, F[rs3]{64}, zext(0, 64), choose(rm<7, rm{8}, FCSR{8}));
if(FLEN==64)
F[rd] <= res;
else { // NaN boxing
val upper[FLEN] <= -1;
F[rd] <= (upper<<64) | res;
}
val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
}
FMSUB.D {
encoding: rs3[4:0] | b01 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1000111;
args_disass:"{name(rd)}, f{rs1}, f{rs2}, f{rs3}";
//F[rd]f<=F[rs1]f * F[rs2]f - F[rs3]f;
val res[64] <= fdispatch_fmadd_d(F[rs1]{64}, F[rs2]{64}, F[rs3]{64}, zext(1, 32), choose(rm<7, rm{8}, FCSR{8}));
if(FLEN==64)
F[rd] <= res;
else { // NaN boxing
val upper[FLEN] <= -1;
F[rd] <= (upper<<64) | res;
}
val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
}
FNMADD.D {
encoding: rs3[4:0] | b01 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1001111;
args_disass:"{name(rd)}, f{rs1}, f{rs2}, f{rs3}";
//F[rd]f<=-F[rs1]f * F[rs2]f + F[rs3]f;
val res[64] <= fdispatch_fmadd_d(F[rs1]{64}, F[rs2]{64}, F[rs3]{64}, zext(2, 32), choose(rm<7, rm{8}, FCSR{8}));
if(FLEN==64)
F[rd] <= res;
else { // NaN boxing
val upper[FLEN] <= -1;
F[rd] <= (upper<<64) | res;
}
val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
}
FNMSUB.D {
encoding: rs3[4:0] | b01 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1001011;
args_disass:"{name(rd)}, f{rs1}, f{rs2}, f{rs3}";
//F[rd]f<=-F[rs1]f * F[rs2]f - F[rs3]f;
val res[64] <= fdispatch_fmadd_d(F[rs1]{64}, F[rs2]{64}, F[rs3]{64}, zext(3, 32), choose(rm<7, rm{8}, FCSR{8}));
if(FLEN==64)
F[rd] <= res;
else { // NaN boxing
val upper[FLEN] <= -1;
F[rd] <= (upper<<64) | res;
}
val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
}
FADD.D {
encoding: b0000001 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"{name(rd)}, f{rs1}, f{rs2}";
// F[rd]f <= F[rs1]f + F[rs2]f;
val res[64] <= fdispatch_fadd_d(F[rs1]{64}, F[rs2]{64}, choose(rm<7, rm{8}, FCSR{8}));
if(FLEN==64)
F[rd] <= res;
else { // NaN boxing
val upper[FLEN] <= -1;
F[rd] <= (upper<<64) | res;
}
val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
}
FSUB.D {
encoding: b0000101 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"{name(rd)}, f{rs1}, f{rs2}";
// F[rd]f <= F[rs1]f - F[rs2]f;
val res[64] <= fdispatch_fsub_d(F[rs1]{64}, F[rs2]{64}, choose(rm<7, rm{8}, FCSR{8}));
if(FLEN==64)
F[rd] <= res;
else { // NaN boxing
val upper[FLEN] <= -1;
F[rd] <= (upper<<64) | res;
}
val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
}
FMUL.D {
encoding: b0001001 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"{name(rd)}, f{rs1}, f{rs2}";
// F[rd]f <= F[rs1]f * F[rs2]f;
val res[64] <= fdispatch_fmul_d(F[rs1]{64}, F[rs2]{64}, choose(rm<7, rm{8}, FCSR{8}));
if(FLEN==64)
F[rd] <= res;
else { // NaN boxing
val upper[FLEN] <= -1;
F[rd] <= (upper<<64) | res;
}
val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
}
FDIV.D {
encoding: b0001101 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"{name(rd)}, f{rs1}, f{rs2}";
// F[rd]f <= F[rs1]f / F[rs2]f;
val res[64] <= fdispatch_fdiv_d(F[rs1]{64}, F[rs2]{64}, choose(rm<7, rm{8}, FCSR{8}));
if(FLEN==64)
F[rd] <= res;
else { // NaN boxing
val upper[FLEN] <= -1;
F[rd] <= (upper<<64) | res;
}
val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
}
FSQRT.D {
encoding: b0101101 | b00000 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"{name(rd)}, f{rs1}";
//F[rd]f<=sqrt(F[rs1]f);
val res[64] <= fdispatch_fsqrt_d(F[rs1]{64}, choose(rm<7, rm{8}, FCSR{8}));
if(FLEN==64)
F[rd] <= res;
else { // NaN boxing
val upper[FLEN] <= -1;
F[rd] <= (upper<<64) | res;
}
val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
}
FSGNJ.D {
encoding: b0010001 | rs2[4:0] | rs1[4:0] | b000 | rd[4:0] | b1010011;
args_disass:"f{rd}, f{rs1}, f{rs2}";
val ONE[64] <= 1;
val MSK1[64] <= ONE<<63;
val MSK2[64] <= MSK1-1;
val res[64] <= (F[rs1]{64} & MSK2) | (F[rs2]{64} & MSK1);
if(FLEN==64)
F[rd] <= res;
else { // NaN boxing
val upper[FLEN] <= -1;
F[rd] <= (upper<<64) | res;
}
}
FSGNJN.D {
encoding: b0010001 | rs2[4:0] | rs1[4:0] | b001 | rd[4:0] | b1010011;
args_disass:"f{rd}, f{rs1}, f{rs2}";
val ONE[64] <= 1;
val MSK1[64] <= ONE<<63;
val MSK2[64] <= MSK1-1;
val res[64] <= (F[rs1]{64} & MSK2) | (~F[rs2]{64} & MSK1);
if(FLEN==64)
F[rd] <= res;
else { // NaN boxing
val upper[FLEN] <= -1;
F[rd] <= (upper<<64) | res;
}
}
FSGNJX.D {
encoding: b0010001 | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b1010011;
args_disass:"f{rd}, f{rs1}, f{rs2}";
val ONE[64] <= 1;
val MSK1[64] <= ONE<<63;
val res[64] <= F[rs1]{64} ^ (F[rs2]{64} & MSK1);
if(FLEN==64)
F[rd] <= res;
else { // NaN boxing
val upper[FLEN] <= -1;
F[rd] <= (upper<<64) | res;
}
}
FMIN.D {
encoding: b0010101 | rs2[4:0] | rs1[4:0] | b000 | rd[4:0] | b1010011;
args_disass:"f{rd}, f{rs1}, f{rs2}";
//F[rd]f<= choose(F[rs1]f<F[rs2]f, F[rs1]f, F[rs2]f);
val res[64] <= fdispatch_fsel_d(F[rs1]{64}, F[rs2]{64}, zext(0, 32));
if(FLEN==64)
F[rd] <= res;
else { // NaN boxing
val upper[FLEN] <= -1;
F[rd] <= (upper<<64) | res;
}
val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
}
FMAX.D {
encoding: b0010101 | rs2[4:0] | rs1[4:0] | b001 | rd[4:0] | b1010011;
args_disass:"f{rd}, f{rs1}, f{rs2}";
//F[rd]f<= choose(F[rs1]f>F[rs2]f, F[rs1]f, F[rs2]f);
val res[64] <= fdispatch_fsel_d(F[rs1]{64}, F[rs2]{64}, zext(1, 32));
if(FLEN==64)
F[rd] <= res;
else { // NaN boxing
val upper[FLEN] <= -1;
F[rd] <= (upper<<64) | res;
}
val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
}
FCVT.S.D {
encoding: b0100000 | b00001 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"f{rd}, f{rs1}";
val res[32] <= fdispatch_fconv_d2f(F[rs1], rm{8});
// NaN boxing
val upper[FLEN] <= -1;
F[rd] <= upper<<32 | zext(res, FLEN);
}
FCVT.D.S {
encoding: b0100001 | b00000 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"f{rd}, f{rs1}";
val res[64] <= fdispatch_fconv_f2d(F[rs1]{32}, rm{8});
if(FLEN==64){
F[rd] <= res;
} else {
val upper[FLEN] <= -1;
F[rd] <= (upper<<64) | res;
}
}
FEQ.D {
encoding: b1010001 | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b1010011;
args_disass:"{name(rd)}, f{rs1}, f{rs2}";
X[rd]<=zext(fdispatch_fcmp_d(F[rs1]{64}, F[rs2]{64}, zext(0, 32)));
val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
}
FLT.D {
encoding: b1010001 | rs2[4:0] | rs1[4:0] | b001 | rd[4:0] | b1010011;
args_disass:"{name(rd)}, f{rs1}, f{rs2}";
X[rd]<=zext(fdispatch_fcmp_d(F[rs1]{64}, F[rs2]{64}, zext(2, 32)));
val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
}
FLE.D {
encoding: b1010001 | rs2[4:0] | rs1[4:0] | b000 | rd[4:0] | b1010011;
args_disass:"{name(rd)}, f{rs1}, f{rs2}";
X[rd]<=zext(fdispatch_fcmp_d(F[rs1]{64}, F[rs2]{64}, zext(1, 32)));
val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
}
FCLASS.D {
encoding: b1110001 | b00000 | rs1[4:0] | b001 | rd[4:0] | b1010011;
args_disass:"{name(rd)}, f{rs1}";
X[rd]<=fdispatch_fclass_d(F[rs1]{64});
}
FCVT.W.D {
encoding: b1100001 | b00000 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"{name(rd)}, f{rs1}";
X[rd]<= sext(fdispatch_fcvt_64_32(F[rs1]{64}, zext(0, 32), rm{8}), XLEN);
val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
}
FCVT.WU.D {
encoding: b1100001 | b00001 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"{name(rd)}, f{rs1}";
//FIXME: should be zext accodring to spec but needs to be sext according to tests
X[rd]<= sext(fdispatch_fcvt_64_32(F[rs1]{64}, zext(1, 32), rm{8}), XLEN);
val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
}
FCVT.D.W {
encoding: b1101001 | b00000 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"f{rd}, {name(rs1)}";
val res[64] <= fdispatch_fcvt_32_64(sext(X[rs1]{32},64), zext(2, 32), rm{8});
if(FLEN==64)
F[rd] <= res;
else { // NaN boxing
val upper[FLEN] <= -1;
F[rd] <= (upper<<64) | res;
}
}
FCVT.D.WU {
encoding: b1101001 | b00001 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"f{rd}, {name(rs1)}";
val res[64] <=fdispatch_fcvt_32_64(zext(X[rs1]{32},64), zext(3,32), rm{8});
if(FLEN==64)
F[rd] <= res;
else { // NaN boxing
val upper[FLEN] <= -1;
F[rd] <= (upper<<64) | res;
}
}
}
}
InsructionSet RV64D extends RV32D{
instructions{
FCVT.L.D {
encoding: b1100001 | b00010 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"{name(rd)}, f{rs1}";
X[rd]<= sext(fdispatch_fcvt_d(F[rs1]{64}, zext(0, 32), rm{8}), XLEN);
val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
}
FCVT.LU.D {
encoding: b1100001 | b00011 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"{name(rd)}, f{rs1}";
X[rd]<= sext(fdispatch_fcvt_d(F[rs1]{64}, zext(1, 32), rm{8}), XLEN);
val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
}
FCVT.D.L {
encoding: b1101001 | b00010 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"f{rd}, {name(rs1)}";
val res[64] <= fdispatch_fcvt_d(sext(X[rs1],64), zext(2, 32), rm{8});
if(FLEN==64)
F[rd] <= res;
else { // NaN boxing
val upper[FLEN] <= -1;
F[rd] <= (upper<<64) | res;
}
}
FCVT.D.LU {
encoding: b1101001 | b00011 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"f{rd}, {name(rs1)}";
val res[64] <=fdispatch_fcvt_d(zext(X[rs1],64), zext(3,32), rm{8});
if(FLEN==64)
F[rd] <= res;
else { // NaN boxing
val upper[FLEN] <= -1;
F[rd] <= (upper<<64) | res;
}
}
FMV.X.D {
encoding: b1110001 | b00000 | rs1[4:0] | b000 | rd[4:0] | b1010011;
args_disass:"{name(rd)}, f{rs1}";
X[rd]<=sext(F[rs1]);
}
FMV.D.X {
encoding: b1111001 | b00000 | rs1[4:0] | b000 | rd[4:0] | b1010011;
args_disass:"f{rd}, {name(rs1)}";
F[rd] <= zext(X[rs1]);
}
}
}

400
gen_input/RVF.core_desc Normal file
View File

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

160
gen_input/RVM.core_desc Normal file
View File

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

View File

@ -1,13 +0,0 @@
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;
}
}

View File

@ -0,0 +1,70 @@
import "RV32I.core_desc"
import "RV64I.core_desc"
import "RVM.core_desc"
import "RVA.core_desc"
import "RVC.core_desc"
import "RVF.core_desc"
import "RVD.core_desc"
Core MNRV32 provides RV32I, RV32IC {
constants {
XLEN:=32;
PCLEN:=32;
// definitions for the architecture wrapper
// XL ZYXWVUTSRQPONMLKJIHGFEDCBA
MISA_VAL:=0b01000000000101000001000100000101;
PGSIZE := 0x1000; //1 << 12;
PGMASK := 0xfff; //PGSIZE-1
}
}
/*
Core RV32IMAC provides RV32I, RV32M, RV32A, RV32IC {
constants {
XLEN:=32;
PCLEN:=32;
// definitions for the architecture wrapper
// XL ZYXWVUTSRQPONMLKJIHGFEDCBA
MISA_VAL:=0b01000000000101000001000100000101;
PGSIZE := 0x1000; //1 << 12;
PGMASK := 0xfff; //PGSIZE-1
}
}
Core RV32GC provides RV32I, RV32M, RV32A, RV32F, RV32D, RV32IC, RV32FC, RV32DC {
constants {
XLEN:=32;
FLEN:=64;
PCLEN:=32;
// definitions for the architecture wrapper
// XL ZYXWVUTSRQPONMLKJIHGFEDCBA
MISA_VAL:=0b01000000000101000001000100101101;
PGSIZE := 0x1000; //1 << 12;
PGMASK := 0xfff; //PGSIZE-1
}
}
Core RV64I provides RV64I {
constants {
XLEN:=64;
PCLEN:=64;
// definitions for the architecture wrapper
// XL ZYXWVUTSRQPONMLKJIHGFEDCBA
MISA_VAL:=0b10000000000001000000000100000000;
PGSIZE := 0x1000; //1 << 12;
PGMASK := 0xfff; //PGSIZE-1
}
}
Core RV64GC provides RV64I, RV64M, RV64A, RV64F, RV64D, RV64IC, RV32FC, RV32DC {
constants {
XLEN:=64;
FLEN:=64;
PCLEN:=64;
// definitions for the architecture wrapper
// XL ZYXWVUTSRQPONMLKJIHGFEDCBA
MISA_VAL:=0b01000000000101000001000100101101;
PGSIZE := 0x1000; //1 << 12;
PGMASK := 0xfff; //PGSIZE-1
}
}
*/

View File

@ -1,177 +0,0 @@
/*******************************************************************************
* Copyright (C) 2017 - 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.
*
*******************************************************************************/
<%
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, 32, 32] // append TRAP_STATE, PENDING_TRAP, ICOUNT, CYCLE, INSTRET, INSTRUCTION, LAST_BRANCH
return regs
}
def getRegisterOffsets(){
def offset = 0
def offsets = []
getRegisterSizes().each { size ->
offsets<<offset
offset+=size/8
}
return offsets
}
def byteSize(int size){
if(size<=8) return 8;
if(size<=16) return 16;
if(size<=32) return 32;
if(size<=64) return 64;
return 128;
}
def getCString(def val){
return val.toString()+'ULL'
}
%>
#ifndef _${coreDef.name.toUpperCase()}_H_
#define _${coreDef.name.toUpperCase()}_H_
// clang-format off
#include <array>
#include <iss/arch/traits.h>
#include <iss/arch_if.h>
#include <iss/vm_if.h>
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<const char*, ${registers.size}> reg_names{
{"${registers.collect{it.name.toLowerCase()}.join('", "')}"}};
static constexpr std::array<const char*, ${registers.size}> reg_aliases{
{"${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, INSTRUCTION, LAST_BRANCH
};
using reg_t = uint${addrDataWidth}_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<iss::address_type::VIRTUAL>;
using phys_addr_t = iss::typed_addr_t<iss::address_type::PHYSICAL>;
static constexpr std::array<const uint32_t, ${getRegisterSizes().size}> reg_bit_widths{
{${getRegisterSizes().join(',')}}};
static constexpr std::array<const uint32_t, ${getRegisterOffsets().size}> reg_byte_offsets{
{${getRegisterOffsets().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 { ${spaces.collect{it.name}.join(', ')}, IMEM = MEM };
enum class opcode_e {<%instructions.eachWithIndex{instr, index -> %>
${instr.instruction.name} = ${index},<%}%>
MAX_OPCODE
};
};
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;
inline uint64_t get_icount() { return reg.icount; }
inline bool should_stop() { return interrupt_sim; }
inline uint64_t stop_code() { return interrupt_sim; }
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; }
#pragma pack(push, 1)
struct ${coreDef.name}_regs {<%
registers.each { reg -> if(reg.size>0) {%>
uint${byteSize(reg.size)}_t ${reg.name} = 0;<%
}}%>
uint32_t trap_state = 0, pending_trap = 0;
uint64_t icount = 0;
uint64_t cycle = 0;
uint64_t instret = 0;
uint32_t instruction = 0;
uint32_t last_branch = 0;
} reg;
#pragma pack(pop)
std::array<address_type, 4> addr_mode;
uint64_t interrupt_sim=0;
<%
def fcsr = registers.find {it.name=='FCSR'}
if(fcsr != null) {%>
uint${fcsr.size}_t get_fcsr(){return reg.FCSR;}
void set_fcsr(uint${fcsr.size}_t val){reg.FCSR = val;}
<%} else { %>
uint32_t get_fcsr(){return 0;}
void set_fcsr(uint32_t val){}
<%}%>
};
}
}
#endif /* _${coreDef.name.toUpperCase()}_H_ */
// clang-format on

View File

@ -1,12 +0,0 @@
{
"${coreDef.name}" : [<%instructions.eachWithIndex{instr,index -> %>${index==0?"":","}
{
"name" : "${instr.name}",
"size" : ${instr.length},
"encoding": "${instr.encoding}",
"mask": "${instr.mask}",
"branch": ${instr.modifiesPC},
"delay" : ${instr.isConditional?"[1,1]":"1"}
}<%}%>
]
}

View File

@ -1,21 +0,0 @@
<% def getInstructionGroups() {
def instrGroups = [:]
instructions.each {
def groupName = it['instruction'].eContainer().name
if(!instrGroups.containsKey(groupName)) {
instrGroups[groupName]=[]
}
instrGroups[groupName]+=it;
}
instrGroups
}%><%int index = 0; getInstructionGroups().each{name, instrList -> %>
${name}: <% instrList.each { %>
${it.instruction.name}:
index: ${index++}
encoding: ${it.encoding}
mask: ${it.mask}<%if(it.attributes.size) {%>
attributes: ${it.attributes}<%}%>
size: ${it.length}
branch: ${it.modifiesPC}
delay: ${it.isConditional?"[1,1]":"1"}<%}}%>

View File

@ -1,131 +0,0 @@
/*******************************************************************************
* 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 <sysc/iss_factory.h>
#include <iss/arch/${coreDef.name.toLowerCase()}.h>
#include <iss/arch/riscv_hart_m_p.h>
#include <iss/arch/riscv_hart_mu_p.h>
#include <sysc/sc_core_adapter.h>
#include <sysc/core_complex.h>
#include <array>
<%
def array_count = coreDef.name.toLowerCase()=="tgc5d" || coreDef.name.toLowerCase()=="tgc5e"? 3 : 2;
%>
namespace iss {
namespace interp {
using namespace sysc;
volatile std::array<bool, ${array_count}> ${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<sysc::tgfs::core_complex*>(data);
auto* cpu = new sc_core_adapter<arch::riscv_hart_m_p<arch::${coreDef.name.toLowerCase()}>>(cc);
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(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<sysc::tgfs::core_complex*>(data);
auto* cpu = new sc_core_adapter<arch::riscv_hart_mu_p<arch::${coreDef.name.toLowerCase()}>>(cc);
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(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<sysc::tgfs::core_complex*>(data);
auto* cpu = new sc_core_adapter<arch::riscv_hart_mu_p<arch::${coreDef.name.toLowerCase()}, (iss::arch::features_e)(iss::arch::FEAT_PMP | iss::arch::FEAT_EXT_N | iss::arch::FEAT_CLIC)>>(cc);
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(cpu), gdb_port)}};
})<%}%>
};
}
#if defined(WITH_LLVM)
namespace llvm {
using namespace sysc;
volatile std::array<bool, ${array_count}> ${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<sysc::tgfs::core_complex*>(data);
auto* cpu = new sc_core_adapter<arch::riscv_hart_m_p<arch::${coreDef.name.toLowerCase()}>>(cc);
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(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<sysc::tgfs::core_complex*>(data);
auto* cpu = new sc_core_adapter<arch::riscv_hart_mu_p<arch::${coreDef.name.toLowerCase()}>>(cc);
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(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<sysc::tgfs::core_complex*>(data);
auto* cpu = new sc_core_adapter<arch::riscv_hart_mu_p<arch::${coreDef.name.toLowerCase()}, (iss::arch::features_e)(iss::arch::FEAT_PMP | iss::arch::FEAT_EXT_N | iss::arch::FEAT_CLIC)>>(cc);
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(cpu), gdb_port)}};
})<%}%>
};
}
#endif
#if defined(WITH_TCC)
namespace tcc {
using namespace sysc;
volatile std::array<bool, ${array_count}> ${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<sysc::tgfs::core_complex*>(data);
auto* cpu = new sc_core_adapter<arch::riscv_hart_m_p<arch::${coreDef.name.toLowerCase()}>>(cc);
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(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<sysc::tgfs::core_complex*>(data);
auto* cpu = new sc_core_adapter<arch::riscv_hart_mu_p<arch::${coreDef.name.toLowerCase()}>>(cc);
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(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<sysc::tgfs::core_complex*>(data);
auto* cpu = new sc_core_adapter<arch::riscv_hart_mu_p<arch::${coreDef.name.toLowerCase()}, (iss::arch::features_e)(iss::arch::FEAT_PMP | iss::arch::FEAT_EXT_N | iss::arch::FEAT_CLIC)>>(cc);
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(cpu), gdb_port)}};
})<%}%>
};
}
#endif
#if defined(WITH_ASMJIT)
namespace asmjit {
using namespace sysc;
volatile std::array<bool, ${array_count}> ${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<sysc::tgfs::core_complex*>(data);
auto* cpu = new sc_core_adapter<arch::riscv_hart_m_p<arch::${coreDef.name.toLowerCase()}>>(cc);
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(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<sysc::tgfs::core_complex*>(data);
auto* cpu = new sc_core_adapter<arch::riscv_hart_mu_p<arch::${coreDef.name.toLowerCase()}>>(cc);
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(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<sysc::tgfs::core_complex*>(data);
auto* cpu = new sc_core_adapter<arch::riscv_hart_mu_p<arch::${coreDef.name.toLowerCase()}, (iss::arch::features_e)(iss::arch::FEAT_PMP | iss::arch::FEAT_EXT_N | iss::arch::FEAT_CLIC)>>(cc);
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(cpu), gdb_port)}};
})<%}%>
};
}
#endif
}
// clang-format on

View File

@ -1,384 +0,0 @@
/*******************************************************************************
* 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 <iss/arch/${coreDef.name.toLowerCase()}.h>
#include <iss/debugger/gdb_session.h>
#include <iss/debugger/server.h>
#include <iss/iss.h>
#include <iss/asmjit/vm_base.h>
#include <asmjit/asmjit.h>
#include <util/logging.h>
#ifndef FMT_HEADER_ONLY
#define FMT_HEADER_ONLY
#endif
#include <fmt/format.h>
#include <array>
#include <iss/debugger/riscv_target_adapter.h>
namespace iss {
namespace asmjit {
namespace ${coreDef.name.toLowerCase()} {
using namespace ::asmjit;
using namespace iss::arch;
using namespace iss::debugger;
template <typename ARCH> class vm_impl : public iss::asmjit::vm_base<ARCH> {
public:
using traits = arch::traits<ARCH>;
using super = typename iss::asmjit::vm_base<ARCH>;
using virt_addr_t = typename super::virt_addr_t;
using phys_addr_t = typename super::phys_addr_t;
using code_word_t = typename super::code_word_t;
using 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<ARCH>::tgt_adapter == nullptr)
vm_base<ARCH>::tgt_adapter = new riscv_target_adapter<ARCH>(srv, this->get_arch());
return vm_base<ARCH>::tgt_adapter;
}
protected:
using super::get_ptr_for;
using super::get_reg;
using super::get_reg_for;
using super::load_reg_from_mem;
using super::write_reg_to_mem;
using super::gen_ext;
using super::gen_read_mem;
using super::gen_write_mem;
using super::gen_wait;
using super::gen_leave;
using super::gen_operation;
using this_class = vm_impl<ARCH>;
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;
void gen_block_prologue(jit_holder& jh) override;
void gen_block_epilogue(jit_holder& jh) override;
inline const char *name(size_t index){return traits::reg_aliases.at(index);}
void gen_instr_prologue(jit_holder& jh);
void gen_instr_epilogue(jit_holder& jh);
inline void gen_raise(jit_holder& jh, uint16_t trap_id, uint16_t cause);
template<unsigned W, typename U, typename S = typename std::make_signed<U>::type>
inline S sext(U from) {
auto mask = (1ULL<<W) - 1;
auto sign_mask = 1ULL<<(W-1);
return (from & mask) | ((from & sign_mask) ? ~mask : 0);
}
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<instruction_descriptor> instrs;
std::vector<decoding_tree_node*> children;
uint32_t submask = std::numeric_limits<uint32_t>::max();
uint32_t value;
decoding_tree_node(uint32_t value) : value(value){}
};
decoding_tree_node* root {nullptr};
const std::array<instruction_descriptor, ${instructions.size}> 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 */
<%instr.disass.eachLine{%>
${it}<%}%>
InvokeNode* call_print_disass;
char* mnemonic_ptr = strdup(mnemonic.c_str());
jh.disass_collection.push_back(mnemonic_ptr);
jh.cc.invoke(&call_print_disass, &print_disass, FuncSignatureT<void, void *, uint64_t, char *>());
call_print_disass->setArg(0, jh.arch_if_ptr);
call_print_disass->setArg(1, pc.val);
call_print_disass->setArg(2, mnemonic_ptr);
}
x86::Compiler& cc = jh.cc;
cc.comment(fmt::format("${instr.name}_{:#x}:",pc.val).c_str());
this->gen_sync(jh, PRE_SYNC, ${idx});
cc.mov(jh.pc, pc.val);
pc = pc+${instr.length/8};
cc.mov(jh.next_pc, pc.val);
gen_instr_prologue(jh);
cc.comment("//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 ) {
x86::Compiler& cc = jh.cc;
cc.comment(fmt::format("illegal_intruction{:#x}:",pc.val).c_str());
this->gen_sync(jh, PRE_SYNC, instr_descr.size());
pc = pc + ((instr & 3) == 3 ? 4 : 2);
gen_instr_prologue(jh);
cc.comment("//behavior:");
gen_instr_epilogue(jh);
this->gen_sync(jh, POST_SYNC, instr_descr.size());
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 <typename ARCH> vm_impl<ARCH>::vm_impl() { this(new ARCH()); }
template <typename ARCH>
vm_impl<ARCH>::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id)
: vm_base<ARCH>(core, core_id, cluster_id) {
root = new decoding_tree_node(std::numeric_limits<uint32_t>::max());
for(auto instr: instr_descr){
root->instrs.push_back(instr);
}
populate_decoding_tree(root);
}
template <typename ARCH>
continuation_e vm_impl<ARCH>::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);
}
template <typename ARCH>
void vm_impl<ARCH>::gen_instr_prologue(jit_holder& jh) {
auto& cc = jh.cc;
cc.comment("//gen_instr_prologue");
cc.inc(get_ptr_for(jh, traits::ICOUNT));
x86::Gp current_trap_state = get_reg_for(jh, traits::TRAP_STATE);
cc.mov(current_trap_state, get_ptr_for(jh, traits::TRAP_STATE));
cc.mov(get_ptr_for(jh, traits::PENDING_TRAP), current_trap_state);
}
template <typename ARCH>
void vm_impl<ARCH>::gen_instr_epilogue(jit_holder& jh) {
auto& cc = jh.cc;
cc.comment("//gen_instr_epilogue");
x86::Gp current_trap_state = get_reg_for(jh, traits::TRAP_STATE);
cc.mov(current_trap_state, get_ptr_for(jh, traits::TRAP_STATE));
cc.cmp(current_trap_state, 0);
cc.jne(jh.trap_entry);
}
template <typename ARCH>
void vm_impl<ARCH>::gen_block_prologue(jit_holder& jh){
jh.pc = load_reg_from_mem(jh, traits::PC);
jh.next_pc = load_reg_from_mem(jh, traits::NEXT_PC);
}
template <typename ARCH>
void vm_impl<ARCH>::gen_block_epilogue(jit_holder& jh){
x86::Compiler& cc = jh.cc;
cc.comment("//gen_block_epilogue");
cc.ret(jh.next_pc);
cc.bind(jh.trap_entry);
this->write_back(jh);
this->gen_sync(jh, POST_SYNC, -1);
x86::Gp current_trap_state = get_reg_for(jh, traits::TRAP_STATE);
cc.mov(current_trap_state, get_ptr_for(jh, traits::TRAP_STATE));
x86::Gp current_pc = get_reg_for(jh, traits::PC);
cc.mov(current_pc, get_ptr_for(jh, traits::PC));
x86::Gp instr = cc.newInt32("instr");
cc.mov(instr, 0); // FIXME:this is not correct
cc.comment("//enter trap call;");
InvokeNode* call_enter_trap;
cc.invoke(&call_enter_trap, &enter_trap, FuncSignatureT<uint64_t, void*, uint64_t, uint64_t, uint64_t>());
call_enter_trap->setArg(0, jh.arch_if_ptr);
call_enter_trap->setArg(1, current_trap_state);
call_enter_trap->setArg(2, current_pc);
call_enter_trap->setArg(3, instr);
x86::Gp current_next_pc = get_reg_for(jh, traits::NEXT_PC);
cc.mov(current_next_pc, get_ptr_for(jh, traits::NEXT_PC));
cc.mov(jh.next_pc, current_next_pc);
cc.mov(get_ptr_for(jh, traits::LAST_BRANCH), std::numeric_limits<uint32_t>::max());
cc.ret(jh.next_pc);
}
template <typename ARCH>
inline void vm_impl<ARCH>::gen_raise(jit_holder& jh, uint16_t trap_id, uint16_t cause) {
auto& cc = jh.cc;
cc.comment("//gen_raise");
auto tmp1 = get_reg_for(jh, traits::TRAP_STATE);
cc.mov(tmp1, 0x80ULL << 24 | (cause << 16) | trap_id);
cc.mov(get_ptr_for(jh, traits::TRAP_STATE), tmp1);
cc.mov(jh.next_pc, std::numeric_limits<uint32_t>::max());
}
} // namespace tgc5c
template <>
std::unique_ptr<vm_if> create<arch::${coreDef.name.toLowerCase()}>(arch::${coreDef.name.toLowerCase()} *core, unsigned short port, bool dump) {
auto ret = new ${coreDef.name.toLowerCase()}::vm_impl<arch::${coreDef.name.toLowerCase()}>(*core, dump);
if (port != 0) debugger::server<debugger::gdb_session>::run_server(ret, port);
return std::unique_ptr<vm_if>(ret);
}
} // namespace asmjit
} // namespace iss
#include <iss/arch/riscv_hart_m_p.h>
#include <iss/arch/riscv_hart_mu_p.h>
#include <iss/factory.h>
namespace iss {
namespace {
volatile std::array<bool, 2> dummy = {
core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|m_p|asmjit", [](unsigned port, void* init_data) -> std::tuple<cpu_ptr, vm_ptr>{
auto* cpu = new iss::arch::riscv_hart_m_p<iss::arch::${coreDef.name.toLowerCase()}>();
auto vm = new asmjit::${coreDef.name.toLowerCase()}::vm_impl<arch::${coreDef.name.toLowerCase()}>(*cpu, false);
if (port != 0) debugger::server<debugger::gdb_session>::run_server(vm, port);
if(init_data){
auto* cb = reinterpret_cast<std::function<void(arch_if*, arch::traits<arch::${coreDef.name.toLowerCase()}>::reg_t, arch::traits<arch::${coreDef.name.toLowerCase()}>::reg_t)>*>(init_data);
cpu->set_semihosting_callback(*cb);
}
return {cpu_ptr{cpu}, vm_ptr{vm}};
}),
core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p|asmjit", [](unsigned port, void* init_data) -> std::tuple<cpu_ptr, vm_ptr>{
auto* cpu = new iss::arch::riscv_hart_mu_p<iss::arch::${coreDef.name.toLowerCase()}>();
auto vm = new asmjit::${coreDef.name.toLowerCase()}::vm_impl<arch::${coreDef.name.toLowerCase()}>(*cpu, false);
if (port != 0) debugger::server<debugger::gdb_session>::run_server(vm, port);
if(init_data){
auto* cb = reinterpret_cast<std::function<void(arch_if*, arch::traits<arch::${coreDef.name.toLowerCase()}>::reg_t, arch::traits<arch::${coreDef.name.toLowerCase()}>::reg_t)>*>(init_data);
cpu->set_semihosting_callback(*cb);
}
return {cpu_ptr{cpu}, vm_ptr{vm}};
})
};
}
}
// clang-format on

View File

@ -1,389 +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.
*
*******************************************************************************/
<%
def nativeTypeSize(int size){
if(size<=8) return 8; else if(size<=16) return 16; else if(size<=32) return 32; else return 64;
}
%>
// clang-format off
#include <iss/arch/${coreDef.name.toLowerCase()}.h>
#include <iss/debugger/gdb_session.h>
#include <iss/debugger/server.h>
#include <iss/iss.h>
#include <iss/interp/vm_base.h>
#include <vm/fp_functions.h>
#include <util/logging.h>
#include <boost/coroutine2/all.hpp>
#include <functional>
#include <exception>
#include <vector>
#include <sstream>
#ifndef FMT_HEADER_ONLY
#define FMT_HEADER_ONLY
#endif
#include <fmt/format.h>
#include <array>
#include <iss/debugger/riscv_target_adapter.h>
namespace iss {
namespace interp {
namespace ${coreDef.name.toLowerCase()} {
using namespace iss::arch;
using namespace iss::debugger;
using namespace std::placeholders;
struct memory_access_exception : public std::exception{
memory_access_exception(){}
};
template <typename ARCH> class vm_impl : public iss::interp::vm_base<ARCH> {
public:
using traits = arch::traits<ARCH>;
using super = typename iss::interp::vm_base<ARCH>;
using virt_addr_t = typename super::virt_addr_t;
using phys_addr_t = typename super::phys_addr_t;
using code_word_t = typename super::code_word_t;
using addr_t = typename super::addr_t;
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();
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 (super::tgt_adapter == nullptr)
super::tgt_adapter = new riscv_target_adapter<ARCH>(srv, this->get_arch());
return super::tgt_adapter;
}
protected:
using this_class = vm_impl<ARCH>;
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 index<traits::reg_aliases.size()?traits::reg_aliases[index]:"illegal";}
virt_addr_t execute_inst(finish_cond_e cond, virt_addr_t start, uint64_t icount_limit) override;
// some compile time constants
inline void raise(uint16_t trap_id, uint16_t cause){
auto trap_val = 0x80ULL << 24 | (cause << 16) | trap_id;
this->core.reg.trap_state = trap_val;
this->template get_reg<uint${addrDataWidth}_t>(traits::NEXT_PC) = std::numeric_limits<uint${addrDataWidth}_t>::max();
}
inline void leave(unsigned lvl){
this->core.leave_trap(lvl);
}
inline void wait(unsigned type){
this->core.wait_until(type);
}
using yield_t = boost::coroutines2::coroutine<void>::push_type;
using coro_t = boost::coroutines2::coroutine<void>::pull_type;
std::vector<coro_t> spawn_blocks;
template<unsigned W, typename U, typename S = typename std::make_signed<U>::type>
inline S sext(U from) {
auto mask = (1ULL<<W) - 1;
auto sign_mask = 1ULL<<(W-1);
return (from & mask) | ((from & sign_mask) ? ~mask : 0);
}
inline void process_spawn_blocks() {
if(spawn_blocks.size()==0) return;
for(auto it = std::begin(spawn_blocks); it!=std::end(spawn_blocks);)
if(*it){
(*it)();
++it;
} else
spawn_blocks.erase(it);
}
<%functions.each{ it.eachLine { %>
${it}<%}%>
<%}%>
private:
/****************************************************************************
* start opcode definitions
****************************************************************************/
struct instruction_descriptor {
size_t length;
uint32_t value;
uint32_t mask;
typename arch::traits<ARCH>::opcode_e op;
};
struct decoding_tree_node{
std::vector<instruction_descriptor> instrs;
std::vector<decoding_tree_node*> children;
uint32_t submask = std::numeric_limits<uint32_t>::max();
uint32_t value;
decoding_tree_node(uint32_t value) : value(value){}
};
decoding_tree_node* root {nullptr};
const std::array<instruction_descriptor, ${instructions.size}> instr_descr = {{
/* entries are: size, valid value, valid mask, function ptr */<%instructions.each{instr -> %>
{${instr.length}, ${instr.encoding}, ${instr.mask}, arch::traits<ARCH>::opcode_e::${instr.instruction.name}},<%}%>
}};
iss::status fetch_ins(virt_addr_t pc, uint8_t * data){
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<ARCH>::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<ARCH>::opcode_e::MAX_OPCODE;
}
};
template <typename CODE_WORD> void debug_fn(CODE_WORD insn) {
volatile CODE_WORD x = insn;
insn = 2 * x;
}
template <typename ARCH> vm_impl<ARCH>::vm_impl() { this(new ARCH()); }
// according to
// https://stackoverflow.com/questions/8871204/count-number-of-1s-in-binary-representation
#ifdef __GCC__
constexpr size_t bit_count(uint32_t u) { return __builtin_popcount(u); }
#elif __cplusplus < 201402L
constexpr size_t uCount(uint32_t u) { return u - ((u >> 1) & 033333333333) - ((u >> 2) & 011111111111); }
constexpr size_t bit_count(uint32_t u) { return ((uCount(u) + (uCount(u) >> 3)) & 030707070707) % 63; }
#else
constexpr size_t bit_count(uint32_t u) {
size_t uCount = u - ((u >> 1) & 033333333333) - ((u >> 2) & 011111111111);
return ((uCount + (uCount >> 3)) & 030707070707) % 63;
}
#endif
template <typename ARCH>
vm_impl<ARCH>::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id)
: vm_base<ARCH>(core, core_id, cluster_id) {
root = new decoding_tree_node(std::numeric_limits<uint32_t>::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){
return (cond & finish_cond_e::COUNT_LIMIT) == finish_cond_e::COUNT_LIMIT;
}
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>
typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e cond, virt_addr_t start, uint64_t icount_limit){
auto pc=start;
auto* PC = reinterpret_cast<uint${addrDataWidth}_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::PC]);
auto* NEXT_PC = reinterpret_cast<uint${addrDataWidth}_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::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<uint8_t*>(&instr);
while(!this->core.should_stop() &&
!(is_count_limit_enabled(cond) && icount >= icount_limit)){
if(fetch_ins(pc, data)!=iss::Ok){
this->do_sync(POST_SYNC, std::numeric_limits<unsigned>::max());
pc.val = super::core.enter_trap(std::numeric_limits<uint64_t>::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_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<unsigned>(inst_id));
try{
switch(inst_id){<%instructions.eachWithIndex{instr, idx -> %>
case arch::traits<ARCH>::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<uint${nativeTypeSize(v.type.size)}_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::${k}0]);<% }else{ %>
auto* ${k} = reinterpret_cast<uint${nativeTypeSize(v.type.size)}_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::${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<unsigned>(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);
} else {
icount++;
instret++;
}
cycle++;
pc.val=*NEXT_PC;
this->core.reg.PC = this->core.reg.NEXT_PC;
this->core.reg.trap_state = this->core.reg.pending_trap;
}
}
return pc;
}
} // namespace ${coreDef.name.toLowerCase()}
template <>
std::unique_ptr<vm_if> create<arch::${coreDef.name.toLowerCase()}>(arch::${coreDef.name.toLowerCase()} *core, unsigned short port, bool dump) {
auto ret = new ${coreDef.name.toLowerCase()}::vm_impl<arch::${coreDef.name.toLowerCase()}>(*core, dump);
if (port != 0) debugger::server<debugger::gdb_session>::run_server(ret, port);
return std::unique_ptr<vm_if>(ret);
}
} // namespace interp
} // namespace iss
#include <iss/arch/riscv_hart_m_p.h>
#include <iss/arch/riscv_hart_mu_p.h>
#include <iss/factory.h>
namespace iss {
namespace {
volatile std::array<bool, 2> dummy = {
core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|m_p|interp", [](unsigned port, void* init_data) -> std::tuple<cpu_ptr, vm_ptr>{
auto* cpu = new iss::arch::riscv_hart_m_p<iss::arch::${coreDef.name.toLowerCase()}>();
auto vm = new interp::${coreDef.name.toLowerCase()}::vm_impl<arch::${coreDef.name.toLowerCase()}>(*cpu, false);
if (port != 0) debugger::server<debugger::gdb_session>::run_server(vm, port);
if(init_data){
auto* cb = reinterpret_cast<semihosting_cb_t<arch::traits<arch::${coreDef.name.toLowerCase()}>::reg_t>*>(init_data);
cpu->set_semihosting_callback(*cb);
}
return {cpu_ptr{cpu}, vm_ptr{vm}};
}),
core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p|interp", [](unsigned port, void* init_data) -> std::tuple<cpu_ptr, vm_ptr>{
auto* cpu = new iss::arch::riscv_hart_mu_p<iss::arch::${coreDef.name.toLowerCase()}>();
auto vm = new interp::${coreDef.name.toLowerCase()}::vm_impl<arch::${coreDef.name.toLowerCase()}>(*cpu, false);
if (port != 0) debugger::server<debugger::gdb_session>::run_server(vm, port);
if(init_data){
auto* cb = reinterpret_cast<semihosting_cb_t<arch::traits<arch::${coreDef.name.toLowerCase()}>::reg_t>*>(init_data);
cpu->set_semihosting_callback(*cb);
}
return {cpu_ptr{cpu}, vm_ptr{vm}};
})
};
}
}
// clang-format on

View File

@ -0,0 +1,9 @@
{
"${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}
}<%}%>
]
}

View File

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

View File

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

View File

@ -0,0 +1,246 @@
/*******************************************************************************
* Copyright (C) 2020 MINRES Technologies GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*******************************************************************************/
#include <iss/arch/${coreDef.name.toLowerCase()}.h>
#include <iss/arch/riscv_hart_msu_vp.h>
#include <iss/debugger/gdb_session.h>
#include <iss/debugger/server.h>
#include <iss/iss.h>
#include <iss/interp/vm_base.h>
#include <util/logging.h>
#include <sstream>
#ifndef FMT_HEADER_ONLY
#define FMT_HEADER_ONLY
#endif
#include <fmt/format.h>
#include <array>
#include <iss/debugger/riscv_target_adapter.h>
namespace iss {
namespace interp {
namespace ${coreDef.name.toLowerCase()} {
using namespace iss::arch;
using namespace iss::debugger;
template <typename ARCH> class vm_impl : public iss::interp::vm_base<ARCH> {
public:
using super = typename iss::interp::vm_base<ARCH>;
using virt_addr_t = typename super::virt_addr_t;
using phys_addr_t = typename super::phys_addr_t;
using code_word_t = typename super::code_word_t;
using addr_t = typename super::addr_t;
using reg_t = typename traits<ARCH>::reg_t;
using iss::interp::vm_base<ARCH>::get_reg;
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 (super::tgt_adapter == nullptr)
super::tgt_adapter = new riscv_target_adapter<ARCH>(srv, this->get_arch());
return super::tgt_adapter;
}
protected:
using this_class = vm_impl<ARCH>;
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<ARCH>::reg_aliases.at(index);}
virt_addr_t execute_inst(virt_addr_t start, std::function<bool(void)> pred) 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(EXTR_MASK32), LUT_SIZE_C = 1 << util::bit_count(EXTR_MASK16) };
std::array<compile_func, LUT_SIZE> lut;
std::array<compile_func, LUT_SIZE_C> lut_00, lut_01, lut_10;
std::array<compile_func, LUT_SIZE> lut_11;
std::array<compile_func *, 4> qlut;
std::array<const uint32_t, 4> lutmasks = {{EXTR_MASK16, EXTR_MASK16, EXTR_MASK16, EXTR_MASK32}};
void expand_bit_mask(int pos, uint32_t mask, uint32_t value, uint32_t valid, uint32_t idx, compile_func lut[],
compile_func f) {
if (pos < 0) {
lut[idx] = f;
} else {
auto bitmask = 1UL << pos;
if ((mask & bitmask) == 0) {
expand_bit_mask(pos - 1, mask, value, valid, idx, lut, f);
} else {
if ((valid & bitmask) == 0) {
expand_bit_mask(pos - 1, mask, value, valid, (idx << 1), lut, f);
expand_bit_mask(pos - 1, mask, value, valid, (idx << 1) + 1, lut, f);
} else {
auto new_val = idx << 1;
if ((value & bitmask) != 0) new_val++;
expand_bit_mask(pos - 1, mask, value, valid, new_val, lut, f);
}
}
}
}
inline uint32_t extract_fields(uint32_t val) { return extract_fields(29, val >> 2, lutmasks[val & 0x3], 0); }
uint32_t extract_fields(int pos, uint32_t val, uint32_t mask, uint32_t lut_val) {
if (pos >= 0) {
auto bitmask = 1UL << pos;
if ((mask & bitmask) == 0) {
lut_val = extract_fields(pos - 1, val, mask, lut_val);
} else {
auto new_val = lut_val << 1;
if ((val & bitmask) != 0) new_val++;
lut_val = extract_fields(pos - 1, val, mask, new_val);
}
}
return lut_val;
}
void raise_trap(uint16_t trap_id, uint16_t cause){
auto trap_val = 0x80ULL << 24 | (cause << 16) | trap_id;
this->template get_reg<uint32_t>(arch::traits<ARCH>::TRAP_STATE) = trap_val;
this->template get_reg<uint32_t>(arch::traits<ARCH>::NEXT_PC) = std::numeric_limits<uint32_t>::max();
}
void leave_trap(unsigned lvl){
this->core.leave_trap(lvl);
auto pc_val = super::template read_mem<reg_t>(traits<ARCH>::CSR, (lvl << 8) + 0x41);
this->template get_reg<reg_t>(arch::traits<ARCH>::NEXT_PC) = pc_val;
this->template get_reg<uint32_t>(arch::traits<ARCH>::LAST_BRANCH) = std::numeric_limits<uint32_t>::max();
}
void wait(unsigned type){
this->core.wait_until(type);
}
private:
/****************************************************************************
* start opcode definitions
****************************************************************************/
struct InstructionDesriptor {
size_t length;
uint32_t value;
uint32_t mask;
compile_func op;
};
const std::array<InstructionDesriptor, ${instructions.size}> 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 definitions */<%instructions.eachWithIndex{instr, idx -> %>
/* instruction ${idx}: ${instr.name} */
compile_ret_t __${generator.functionName(instr.name)}(virt_addr_t& pc, code_word_t instr){<%instr.code.eachLine{%>
${it}<%}%>
}
<%}%>
/****************************************************************************
* end opcode definitions
****************************************************************************/
compile_ret_t illegal_intruction(virt_addr_t &pc, code_word_t instr) {
pc = pc + ((instr & 3) == 3 ? 4 : 2);
return pc;
}
};
template <typename CODE_WORD> void debug_fn(CODE_WORD insn) {
volatile CODE_WORD x = insn;
insn = 2 * x;
}
template <typename ARCH> vm_impl<ARCH>::vm_impl() { this(new ARCH()); }
template <typename ARCH>
vm_impl<ARCH>::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id)
: vm_base<ARCH>(core, core_id, cluster_id) {
qlut[0] = lut_00.data();
qlut[1] = lut_01.data();
qlut[2] = lut_10.data();
qlut[3] = lut_11.data();
for (auto instr : instr_descr) {
auto quantrant = instr.value & 0x3;
expand_bit_mask(29, lutmasks[quantrant], instr.value >> 2, instr.mask >> 2, 0, qlut[quantrant], instr.op);
}
}
template <typename ARCH>
typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(virt_addr_t start, std::function<bool(void)> pred) {
// we fetch at max 4 byte, alignment is 2
enum {TRAP_ID=1<<16};
const typename traits<ARCH>::addr_t upper_bits = ~traits<ARCH>::PGMASK;
code_word_t insn = 0;
auto *const data = (uint8_t *)&insn;
auto pc=start;
while(pred){
auto paddr = this->core.v2p(pc);
if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary
if (this->core.read(paddr, 2, data) != iss::Ok) throw trap_access(TRAP_ID, pc.val);
if ((insn & 0x3) == 0x3) // this is a 32bit instruction
if (this->core.read(this->core.v2p(pc + 2), 2, data + 2) != iss::Ok) throw trap_access(TRAP_ID, pc.val);
} else {
if (this->core.read(paddr, 4, data) != 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'
auto lut_val = extract_fields(insn);
auto f = qlut[insn & 0x3][lut_val];
if (!f)
f = &this_class::illegal_intruction;
pc = (this->*f)(pc, insn);
}
return pc;
}
} // namespace mnrv32
template <>
std::unique_ptr<vm_if> create<arch::${coreDef.name.toLowerCase()}>(arch::${coreDef.name.toLowerCase()} *core, unsigned short port, bool dump) {
auto ret = new ${coreDef.name.toLowerCase()}::vm_impl<arch::${coreDef.name.toLowerCase()}>(*core, dump);
if (port != 0) debugger::server<debugger::gdb_session>::run_server(ret, port);
return std::unique_ptr<vm_if>(ret);
}
} // namespace interp
} // namespace iss

View File

@ -1,394 +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.
*
*******************************************************************************/
// clang-format off
#include <iss/arch/${coreDef.name.toLowerCase()}.h>
#include <iss/debugger/gdb_session.h>
#include <iss/debugger/server.h>
#include <iss/iss.h>
#include <iss/llvm/vm_base.h>
#include <util/logging.h>
#ifndef FMT_HEADER_ONLY
#define FMT_HEADER_ONLY
#endif
#include <fmt/format.h>
#include <array>
#include <iss/debugger/riscv_target_adapter.h>
namespace iss {
namespace llvm {
namespace fp_impl {
void add_fp_functions_2_module(::llvm::Module *, unsigned, unsigned);
}
namespace ${coreDef.name.toLowerCase()} {
using namespace ::llvm;
using namespace iss::arch;
using namespace iss::debugger;
template <typename ARCH> class vm_impl : public iss::llvm::vm_base<ARCH> {
public:
using traits = arch::traits<ARCH>;
using super = typename iss::llvm::vm_base<ARCH>;
using virt_addr_t = typename super::virt_addr_t;
using phys_addr_t = typename super::phys_addr_t;
using code_word_t = typename super::code_word_t;
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<ARCH>::tgt_adapter == nullptr)
vm_base<ARCH>::tgt_adapter = new riscv_target_adapter<ARCH>(srv, this->get_arch());
return vm_base<ARCH>::tgt_adapter;
}
protected:
using vm_base<ARCH>::get_reg_ptr;
inline const char *name(size_t index){return traits::reg_aliases.at(index);}
template <typename T> inline ConstantInt *size(T type) {
return ConstantInt::get(getContext(), APInt(32, type->getType()->getScalarSizeInBits()));
}
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);
}
inline Value *gen_choose(Value *cond, Value *trueVal, Value *falseVal, unsigned size) {
return super::gen_cond_assign(cond, this->gen_ext(trueVal, size), this->gen_ext(falseVal, size));
}
std::tuple<continuation_e, BasicBlock *> gen_single_inst_behavior(virt_addr_t &, unsigned int &, BasicBlock *) override;
void gen_leave_behavior(BasicBlock *leave_blk) override;
void gen_raise_trap(uint16_t trap_id, uint16_t cause);
void gen_leave_trap(unsigned lvl);
void gen_wait(unsigned type);
void gen_trap_behavior(BasicBlock *) override;
void gen_instr_epilogue(BasicBlock *bb);
inline Value *gen_reg_load(unsigned i, unsigned level = 0) {
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));
this->builder.CreateStore(next_pc_v, get_reg_ptr(reg_num), true);
}
// some compile time constants
using this_class = vm_impl<ARCH>;
using compile_func = std::tuple<continuation_e, BasicBlock *> (this_class::*)(virt_addr_t &pc,
code_word_t instr,
BasicBlock *bb);
template<unsigned W, typename U, typename S = typename std::make_signed<U>::type>
inline S sext(U from) {
auto mask = (1ULL<<W) - 1;
auto sign_mask = 1ULL<<(W-1);
return (from & mask) | ((from & sign_mask) ? ~mask : 0);
}
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<instruction_descriptor> instrs;
std::vector<decoding_tree_node*> children;
uint32_t submask = std::numeric_limits<uint32_t>::max();
uint32_t value;
decoding_tree_node(uint32_t value) : value(value){}
};
decoding_tree_node* root {nullptr};
const std::array<instruction_descriptor, ${instructions.size}> 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} */
std::tuple<continuation_e, BasicBlock*> __${generator.functionName(instr.name)}(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){
uint64_t PC = pc.val;
<%instr.fields.eachLine{%>${it}
<%}%>if(this->disass_enabled){
/* generate console output when executing the command */<%instr.disass.eachLine{%>
${it}<%}%>
}
bb->setName(fmt::format("${instr.name}_0x{:X}",pc.val));
this->gen_sync(PRE_SYNC,${idx});
auto cur_pc_val = this->gen_const(32,pc.val);
pc=pc+ ${instr.length/8};
this->gen_set_pc(pc, traits::NEXT_PC);
/*generate behavior*/
<%instr.behavior.eachLine{%>${it}
<%}%>
this->gen_instr_epilogue(bb);
this->gen_sync(POST_SYNC, ${idx});
this->builder.CreateBr(bb);
return returnValue;
}
<%}%>
/****************************************************************************
* end opcode definitions
****************************************************************************/
std::tuple<continuation_e, BasicBlock *> illegal_intruction(virt_addr_t &pc, code_word_t instr, BasicBlock *bb) {
this->gen_sync(iss::PRE_SYNC, instr_descr.size());
this->builder.CreateStore(this->builder.CreateLoad(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(this->get_typeptr(traits::ICOUNT), get_reg_ptr(traits::ICOUNT), true),
this->gen_const(64U, 1)),
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_instr_epilogue(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 <typename CODE_WORD> void debug_fn(CODE_WORD instr) {
volatile CODE_WORD x = instr;
instr = 2 * x;
}
template <typename ARCH> vm_impl<ARCH>::vm_impl() { this(new ARCH()); }
template <typename ARCH>
vm_impl<ARCH>::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id)
: vm_base<ARCH>(core, core_id, cluster_id) {
root = new decoding_tree_node(std::numeric_limits<uint32_t>::max());
for(auto instr:instr_descr){
root->instrs.push_back(instr);
}
populate_decoding_tree(root);
}
template <typename ARCH>
std::tuple<continuation_e, BasicBlock *>
vm_impl<ARCH>::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, BasicBlock *this_block) {
// we fetch at max 4 byte, alignment is 2
enum {TRAP_ID=1<<16};
code_word_t instr = 0;
// const typename traits::addr_t upper_bits = ~traits::PGMASK;
phys_addr_t paddr(pc);
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 (instr == 0x0000006f || (instr&0xffff)==0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0'
// curr pc on stack
++inst_cnt;
auto f = decode_instr(root, instr);
if (f == nullptr) {
f = &this_class::illegal_intruction;
}
return (this->*f)(pc, instr, this_block);
}
template <typename ARCH>
void vm_impl<ARCH>::gen_leave_behavior(BasicBlock *leave_blk) {
this->builder.SetInsertPoint(leave_blk);
this->builder.CreateRet(this->builder.CreateLoad(this->get_typeptr(traits::NEXT_PC),get_reg_ptr(traits::NEXT_PC), false));
}
template <typename ARCH>
void vm_impl<ARCH>::gen_raise_trap(uint16_t trap_id, uint16_t cause) {
auto *TRAP_val = this->gen_const(32, 0x80 << 24 | (cause << 16) | trap_id);
this->builder.CreateStore(TRAP_val, get_reg_ptr(traits::TRAP_STATE), true);
this->builder.CreateStore(this->gen_const(32U, std::numeric_limits<uint32_t>::max()), get_reg_ptr(traits::LAST_BRANCH), false);
}
template <typename ARCH>
void vm_impl<ARCH>::gen_leave_trap(unsigned lvl) {
std::vector<Value *> args{ this->core_ptr, ConstantInt::get(getContext(), APInt(64, lvl)) };
this->builder.CreateCall(this->mod->getFunction("leave_trap"), args);
auto *PC_val = this->gen_read_mem(traits::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<uint32_t>::max()), get_reg_ptr(traits::LAST_BRANCH), false);
}
template <typename ARCH>
void vm_impl<ARCH>::gen_wait(unsigned type) {
std::vector<Value *> args{ this->core_ptr, ConstantInt::get(getContext(), APInt(64, type)) };
this->builder.CreateCall(this->mod->getFunction("wait"), args);
}
template <typename ARCH>
void vm_impl<ARCH>::gen_trap_behavior(BasicBlock *trap_blk) {
this->builder.SetInsertPoint(trap_blk);
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<uint32_t>::max()),
get_reg_ptr(traits::LAST_BRANCH), false);
std::vector<Value *> args{this->core_ptr, this->adj_to64(trap_state_val),
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(this->get_typeptr(traits::NEXT_PC), get_reg_ptr(traits::NEXT_PC), false);
this->builder.CreateRet(trap_addr_val);
}
template <typename ARCH>
void vm_impl<ARCH>::gen_instr_epilogue(BasicBlock *bb) {
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))),
target_bb, this->trap_blk, 1);
this->builder.SetInsertPoint(target_bb);
}
} // namespace ${coreDef.name.toLowerCase()}
template <>
std::unique_ptr<vm_if> create<arch::${coreDef.name.toLowerCase()}>(arch::${coreDef.name.toLowerCase()} *core, unsigned short port, bool dump) {
auto ret = new ${coreDef.name.toLowerCase()}::vm_impl<arch::${coreDef.name.toLowerCase()}>(*core, dump);
if (port != 0) debugger::server<debugger::gdb_session>::run_server(ret, port);
return std::unique_ptr<vm_if>(ret);
}
} // namespace llvm
} // namespace iss
#include <iss/arch/riscv_hart_m_p.h>
#include <iss/arch/riscv_hart_mu_p.h>
#include <iss/factory.h>
namespace iss {
namespace {
volatile std::array<bool, 2> dummy = {
core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|m_p|llvm", [](unsigned port, void* init_data) -> std::tuple<cpu_ptr, vm_ptr>{
auto* cpu = new iss::arch::riscv_hart_m_p<iss::arch::${coreDef.name.toLowerCase()}>();
auto vm = new llvm::${coreDef.name.toLowerCase()}::vm_impl<arch::${coreDef.name.toLowerCase()}>(*cpu, false);
if (port != 0) debugger::server<debugger::gdb_session>::run_server(vm, port);
if(init_data){
auto* cb = reinterpret_cast<std::function<void(arch_if*, arch::traits<arch::${coreDef.name.toLowerCase()}>::reg_t*, arch::traits<arch::${coreDef.name.toLowerCase()}>::reg_t*)>*>(init_data);
cpu->set_semihosting_callback(*cb);
}
return {cpu_ptr{cpu}, vm_ptr{vm}};
}),
core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p|llvm", [](unsigned port, void* init_data) -> std::tuple<cpu_ptr, vm_ptr>{
auto* cpu = new iss::arch::riscv_hart_mu_p<iss::arch::${coreDef.name.toLowerCase()}>();
auto vm = new llvm::${coreDef.name.toLowerCase()}::vm_impl<arch::${coreDef.name.toLowerCase()}>(*cpu, false);
if (port != 0) debugger::server<debugger::gdb_session>::run_server(vm, port);
if(init_data){
auto* cb = reinterpret_cast<std::function<void(arch_if*, arch::traits<arch::${coreDef.name.toLowerCase()}>::reg_t*, arch::traits<arch::${coreDef.name.toLowerCase()}>::reg_t*)>*>(init_data);
cpu->set_semihosting_callback(*cb);
}
return {cpu_ptr{cpu}, vm_ptr{vm}};
})
};
}
}
// clang-format on

View File

@ -0,0 +1,9 @@
{
"${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}
}<%}%>
]
}

View File

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

View File

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

View File

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

View File

@ -0,0 +1,9 @@
{
"${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}
}<%}%>
]
}

View File

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

View File

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

View File

@ -29,8 +29,9 @@
* POSSIBILITY OF SUCH DAMAGE.
*
*******************************************************************************/
// clang-format off
#include <iss/arch/${coreDef.name.toLowerCase()}.h>
#include <iss/arch/riscv_hart_msu_vp.h>
#include <iss/debugger/gdb_session.h>
#include <iss/debugger/server.h>
#include <iss/iss.h>
@ -54,12 +55,10 @@ using namespace iss::debugger;
template <typename ARCH> class vm_impl : public iss::tcc::vm_base<ARCH> {
public:
using traits = arch::traits<ARCH>;
using super = typename iss::tcc::vm_base<ARCH>;
using virt_addr_t = typename super::virt_addr_t;
using phys_addr_t = typename super::phys_addr_t;
using code_word_t = typename super::code_word_t;
using mem_type_e = typename traits::mem_type_e;
using addr_t = typename super::addr_t;
using tu_builder = typename super::tu_builder;
@ -83,7 +82,7 @@ protected:
using compile_ret_t = std::tuple<continuation_e>;
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<ARCH>::reg_aliases.at(index);}
void setup_module(std::string m) override {
super::setup_module(m);
@ -105,10 +104,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<ARCH>::NEXT_PC:
tu("*next_pc = {:#x};", pc.val);
break;
case traits::PC:
case traits<ARCH>::PC:
tu("*pc = {:#x};", pc.val);
break;
default:
@ -120,62 +119,80 @@ 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) };
template<unsigned W, typename U, typename S = typename std::make_signed<U>::type>
inline S sext(U from) {
auto mask = (1ULL<<W) - 1;
auto sign_mask = 1ULL<<(W-1);
return (from & mask) | ((from & sign_mask) ? ~mask : 0);
std::array<compile_func, LUT_SIZE> lut;
std::array<compile_func, LUT_SIZE_C> lut_00, lut_01, lut_10;
std::array<compile_func, LUT_SIZE> lut_11;
std::array<compile_func *, 4> qlut;
std::array<const uint32_t, 4> lutmasks = {{EXTR_MASK16, EXTR_MASK16, EXTR_MASK16, EXTR_MASK32}};
void expand_bit_mask(int pos, uint32_t mask, uint32_t value, uint32_t valid, uint32_t idx, compile_func lut[],
compile_func f) {
if (pos < 0) {
lut[idx] = f;
} else {
auto bitmask = 1UL << pos;
if ((mask & bitmask) == 0) {
expand_bit_mask(pos - 1, mask, value, valid, idx, lut, f);
} else {
if ((valid & bitmask) == 0) {
expand_bit_mask(pos - 1, mask, value, valid, (idx << 1), lut, f);
expand_bit_mask(pos - 1, mask, value, valid, (idx << 1) + 1, lut, f);
} else {
auto new_val = idx << 1;
if ((value & bitmask) != 0) new_val++;
expand_bit_mask(pos - 1, mask, value, valid, new_val, lut, f);
}
}
}
}
inline uint32_t extract_fields(uint32_t val) { return extract_fields(29, val >> 2, lutmasks[val & 0x3], 0); }
uint32_t extract_fields(int pos, uint32_t val, uint32_t mask, uint32_t lut_val) {
if (pos >= 0) {
auto bitmask = 1UL << pos;
if ((mask & bitmask) == 0) {
lut_val = extract_fields(pos - 1, val, mask, lut_val);
} else {
auto new_val = lut_val << 1;
if ((val & bitmask) != 0) new_val++;
lut_val = extract_fields(pos - 1, val, mask, new_val);
}
}
return lut_val;
}
private:
/****************************************************************************
* start opcode definitions
****************************************************************************/
struct instruction_descriptor {
struct InstructionDesriptor {
size_t length;
uint32_t value;
uint32_t mask;
compile_func op;
};
struct decoding_tree_node{
std::vector<instruction_descriptor> instrs;
std::vector<decoding_tree_node*> children;
uint32_t submask = std::numeric_limits<uint32_t>::max();
uint32_t value;
decoding_tree_node(uint32_t value) : value(value){}
};
decoding_tree_node* root {nullptr};
const std::array<instruction_descriptor, ${instructions.size}> instr_descr = {{
const std::array<InstructionDesriptor, ${instructions.size}> 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 ${instr.instruction.name} */
{${instr.length}, ${instr.value}, ${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){
tu("${instr.name}_{:#010x}:", pc.val);
vm_base<ARCH>::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{%>
compile_ret_t __${generator.functionName(instr.name)}(virt_addr_t& pc, code_word_t instr, tu_builder& tu){<%instr.code.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<ARCH>::gen_sync(tu, POST_SYNC,${idx});
return returnValue;
}
<%}%>
/****************************************************************************
* end opcode definitions
@ -188,64 +205,11 @@ 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 <typename CODE_WORD> void debug_fn(CODE_WORD instr) {
volatile CODE_WORD x = instr;
instr = 2 * x;
template <typename CODE_WORD> void debug_fn(CODE_WORD insn) {
volatile CODE_WORD x = insn;
insn = 2 * x;
}
template <typename ARCH> vm_impl<ARCH>::vm_impl() { this(new ARCH()); }
@ -253,11 +217,14 @@ template <typename ARCH> vm_impl<ARCH>::vm_impl() { this(new ARCH()); }
template <typename ARCH>
vm_impl<ARCH>::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id)
: vm_base<ARCH>(core, core_id, cluster_id) {
root = new decoding_tree_node(std::numeric_limits<uint32_t>::max());
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) {
root->instrs.push_back(instr);
auto quantrant = instr.value & 0x3;
expand_bit_mask(29, lutmasks[quantrant], instr.value >> 2, instr.mask >> 2, 0, qlut[quantrant], instr.op);
}
populate_decoding_tree(root);
}
template <typename ARCH>
@ -265,40 +232,41 @@ std::tuple<continuation_e>
vm_impl<ARCH>::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 instr = 0;
code_word_t insn = 0;
const typename traits<ARCH>::addr_t upper_bits = ~traits<ARCH>::PGMASK;
phys_addr_t paddr(pc);
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<uint8_t*>(&instr));
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 (instr == 0x0000006f || (instr&0xffff)==0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0'
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'
// curr pc on stack
++inst_cnt;
auto f = decode_instr(root, instr);
auto lut_val = extract_fields(insn);
auto f = qlut[insn & 0x3][lut_val];
if (f == nullptr) {
f = &this_class::illegal_intruction;
}
return (this->*f)(pc, instr, tu);
return (this->*f)(pc, insn, tu);
}
template <typename ARCH> void vm_impl<ARCH>::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(traits::NEXT_PC, tu.constant(std::numeric_limits<uint32_t>::max(), 32));
tu.store(tu.constant(std::numeric_limits<uint32_t>::max(), 32),traits<ARCH>::LAST_BRANCH);
}
template <typename ARCH> void vm_impl<ARCH>::gen_leave_trap(tu_builder& tu, unsigned lvl) {
tu("leave_trap(core_ptr, {});", lvl);
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<uint32_t>::max(), 32));
tu.store(tu.read_mem(traits<ARCH>::CSR, (lvl << 8) + 0x41, traits<ARCH>::XLEN),traits<ARCH>::NEXT_PC);
tu.store(tu.constant(std::numeric_limits<uint32_t>::max(), 32),traits<ARCH>::LAST_BRANCH);
}
template <typename ARCH> void vm_impl<ARCH>::gen_wait(tu_builder& tu, unsigned type) {
@ -306,13 +274,12 @@ template <typename ARCH> void vm_impl<ARCH>::gen_wait(tu_builder& tu, unsigned t
template <typename ARCH> void vm_impl<ARCH>::gen_trap_behavior(tu_builder& tu) {
tu("trap_entry:");
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<uint32_t>::max(),32));
tu("enter_trap(core_ptr, *trap_state, *pc);");
tu.store(tu.constant(std::numeric_limits<uint32_t>::max(),32),traits<ARCH>::LAST_BRANCH);
tu("return *next_pc;");
}
} // namespace ${coreDef.name.toLowerCase()}
} // namespace mnrv32
template <>
std::unique_ptr<vm_if> create<arch::${coreDef.name.toLowerCase()}>(arch::${coreDef.name.toLowerCase()} *core, unsigned short port, bool dump) {
@ -320,36 +287,5 @@ std::unique_ptr<vm_if> create<arch::${coreDef.name.toLowerCase()}>(arch::${coreD
if (port != 0) debugger::server<debugger::gdb_session>::run_server(ret, port);
return std::unique_ptr<vm_if>(ret);
}
} // namesapce tcc
}
} // namespace iss
#include <iss/arch/riscv_hart_m_p.h>
#include <iss/arch/riscv_hart_mu_p.h>
#include <iss/factory.h>
namespace iss {
namespace {
volatile std::array<bool, 2> dummy = {
core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|m_p|tcc", [](unsigned port, void* init_data) -> std::tuple<cpu_ptr, vm_ptr>{
auto* cpu = new iss::arch::riscv_hart_m_p<iss::arch::${coreDef.name.toLowerCase()}>();
auto vm = new tcc::${coreDef.name.toLowerCase()}::vm_impl<arch::${coreDef.name.toLowerCase()}>(*cpu, false);
if (port != 0) debugger::server<debugger::gdb_session>::run_server(vm, port);
if(init_data){
auto* cb = reinterpret_cast<std::function<void(arch_if*, arch::traits<arch::${coreDef.name.toLowerCase()}>::reg_t, arch::traits<arch::${coreDef.name.toLowerCase()}>::reg_t)>*>(init_data);
cpu->set_semihosting_callback(*cb);
}
return {cpu_ptr{cpu}, vm_ptr{vm}};
}),
core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p|tcc", [](unsigned port, void* init_data) -> std::tuple<cpu_ptr, vm_ptr>{
auto* cpu = new iss::arch::riscv_hart_mu_p<iss::arch::${coreDef.name.toLowerCase()}>();
auto vm = new tcc::${coreDef.name.toLowerCase()}::vm_impl<arch::${coreDef.name.toLowerCase()}>(*cpu, false);
if (port != 0) debugger::server<debugger::gdb_session>::run_server(vm, port);
if(init_data){
auto* cb = reinterpret_cast<std::function<void(arch_if*, arch::traits<arch::${coreDef.name.toLowerCase()}>::reg_t, arch::traits<arch::${coreDef.name.toLowerCase()}>::reg_t)>*>(init_data);
cpu->set_semihosting_callback(*cb);
}
return {cpu_ptr{cpu}, vm_ptr{vm}};
})
};
}
}
// clang-format on

252
incl/iss/arch/mnrv32.h Normal file
View File

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

File diff suppressed because it is too large Load Diff

316
incl/iss/arch/rv32gc.h Normal file
View File

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

250
incl/iss/arch/rv32imac.h Normal file
View File

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

316
incl/iss/arch/rv64gc.h Normal file
View File

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

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

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

View File

@ -84,7 +84,8 @@ public:
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<uint8_t>& buf, std::vector<uint8_t>& avail_buf) override;
status read_single_register(unsigned int reg_no, std::vector<uint8_t> &buf,
std::vector<uint8_t> &avail_buf) override;
/* Write one register. buf is 4-byte aligned and it is in target byte
order */
@ -102,8 +103,8 @@ public:
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<rp_thread_ref>& result, size_t max_num, size_t& num,
bool& done) override;
status thread_list_query(int first, const rp_thread_ref &arg, std::vector<rp_thread_ref> &result, size_t max_num,
size_t &num, bool &done) override;
status current_thread_query(rp_thread_ref &thread) override;
@ -119,11 +120,12 @@ public:
status packetsize_query(std::string &out_buf) override;
status add_break(break_type type, uint64_t addr, unsigned int length) override;
status add_break(int type, uint64_t addr, unsigned int length) override;
status remove_break(break_type type, uint64_t addr, unsigned int length) override;
status remove_break(int 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<void(unsigned)> stop_callback) override;
status resume_from_addr(bool step, int sig, uint64_t addr, rp_thread_ref thread,
std::function<void(unsigned)> stop_callback) override;
status target_xml_query(std::string &out_buf) override;
@ -156,8 +158,9 @@ template <typename ARCH> status riscv_target_adapter<ARCH>::is_thread_alive(rp_t
* set if all threads are processed.
*/
template <typename ARCH>
status riscv_target_adapter<ARCH>::thread_list_query(int first, const rp_thread_ref& arg, std::vector<rp_thread_ref>& result,
size_t max_num, size_t& num, bool& done) {
status riscv_target_adapter<ARCH>::thread_list_query(int first, const rp_thread_ref &arg,
std::vector<rp_thread_ref> &result, size_t max_num, size_t &num,
bool &done) {
if (first == 0) {
result.clear();
result.push_back(thread_idx);
@ -173,69 +176,61 @@ template <typename ARCH> status riscv_target_adapter<ARCH>::current_thread_query
return Ok;
}
template <typename ARCH> status riscv_target_adapter<ARCH>::read_registers(std::vector<uint8_t>& data, std::vector<uint8_t>& avail) {
CPPLOG(TRACE) << "reading target registers";
template <typename ARCH>
status riscv_target_adapter<ARCH>::read_registers(std::vector<uint8_t> &data, std::vector<uint8_t> &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<ARCH>::X0;
for(size_t reg_no = start_reg; reg_no < start_reg + 33 /*arch::traits<ARCH>::NUM_REGS*/; ++reg_no) {
auto reg_width = arch::traits<ARCH>::reg_bit_widths[reg_no] / 8;
for (size_t reg_no = 0; reg_no < arch::traits<ARCH>::NUM_REGS; ++reg_no) {
auto reg_width = arch::traits<ARCH>::reg_bit_widths[static_cast<typename arch::traits<ARCH>::reg_e>(reg_no)] / 8;
unsigned offset = traits<ARCH>::reg_byte_offsets[reg_no];
for (size_t j = 0; j < reg_width; ++j) {
data.push_back(*(reg_base + offset + j));
avail.push_back(0xff);
}
// if(arch::traits<ARCH>::XLEN < 64)
// for(unsigned j=0; j<4; ++j){
// data.push_back(0);
// avail.push_back(0xff);
// }
}
// work around fill with F type registers
// if (arch::traits<ARCH>::NUM_REGS < 65) {
// auto reg_width = sizeof(typename arch::traits<ARCH>::reg_t);
// for (size_t reg_no = 0; reg_no < 33; ++reg_no) {
// for (size_t j = 0; j < reg_width; ++j) {
if (arch::traits<ARCH>::NUM_REGS < 65) {
auto reg_width = sizeof(typename arch::traits<ARCH>::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<ARCH>::XLEN < 64)
// for(unsigned j=0; j<4; ++j){
// data.push_back(0x0);
// avail.push_back(0x00);
// }
// // if(arch::traits<ARCH>::XLEN < 64)
// // for(unsigned j=0; j<4; ++j){
// // data.push_back(0x0);
// // avail.push_back(0x00);
// // }
// }
// }
}
}
return Ok;
}
template <typename ARCH> status riscv_target_adapter<ARCH>::write_registers(const std::vector<uint8_t> &data) {
auto start_reg = arch::traits<ARCH>::X0;
auto reg_count = arch::traits<ARCH>::NUM_REGS;
auto *reg_base = core->get_regs_base_ptr();
auto iter = data.data();
bool e_ext = arch::traits<ARCH>::PC < 32;
for(size_t reg_no = 0; reg_no < start_reg + 33 /*arch::traits<ARCH>::NUM_REGS*/; ++reg_no) {
if(e_ext && reg_no > 15) {
if(reg_no == 32) {
auto reg_width = arch::traits<ARCH>::reg_bit_widths[arch::traits<ARCH>::PC] / 8;
auto offset = traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::PC];
std::copy(iter, iter + reg_width, reg_base);
} else {
const uint64_t zero_val = 0;
auto reg_width = arch::traits<ARCH>::reg_bit_widths[15] / 8;
auto iter = (uint8_t*)&zero_val;
std::copy(iter, iter + reg_width, reg_base);
}
} else {
auto reg_width = arch::traits<ARCH>::reg_bit_widths[reg_no] / 8;
for (size_t reg_no = 0; reg_no < reg_count; ++reg_no) {
auto reg_width = arch::traits<ARCH>::reg_bit_widths[static_cast<typename arch::traits<ARCH>::reg_e>(reg_no)] / 8;
auto offset = traits<ARCH>::reg_byte_offsets[reg_no];
std::copy(iter, iter + reg_width, reg_base);
iter += 4;
reg_base += offset;
}
}
return Ok;
}
template <typename ARCH>
status riscv_target_adapter<ARCH>::read_single_register(unsigned int reg_no, std::vector<uint8_t>& data, std::vector<uint8_t>& avail) {
status riscv_target_adapter<ARCH>::read_single_register(unsigned int reg_no, std::vector<uint8_t> &data,
std::vector<uint8_t> &avail) {
if (reg_no < 65) {
// auto reg_size = arch::traits<ARCH>::reg_bit_width(static_cast<typename
// arch::traits<ARCH>::reg_e>(reg_no))/8;
@ -256,7 +251,8 @@ status riscv_target_adapter<ARCH>::read_single_register(unsigned int reg_no, std
return data.size() > 0 ? Ok : Err;
}
template <typename ARCH> status riscv_target_adapter<ARCH>::write_single_register(unsigned int reg_no, const std::vector<uint8_t>& data) {
template <typename ARCH>
status riscv_target_adapter<ARCH>::write_single_register(unsigned int reg_no, const std::vector<uint8_t> &data) {
if (reg_no < 65) {
auto *reg_base = core->get_regs_base_ptr();
auto reg_width = arch::traits<ARCH>::reg_bit_widths[static_cast<typename arch::traits<ARCH>::reg_e>(reg_no)] / 8;
@ -286,16 +282,21 @@ status riscv_target_adapter<ARCH>::process_query(unsigned int& mask, const rp_th
return NotSupported;
}
template <typename ARCH> status riscv_target_adapter<ARCH>::offsets_query(uint64_t& text, uint64_t& data, uint64_t& bss) {
template <typename ARCH>
status riscv_target_adapter<ARCH>::offsets_query(uint64_t &text, uint64_t &data, uint64_t &bss) {
text = 0;
data = 0;
bss = 0;
return Ok;
}
template <typename ARCH> status riscv_target_adapter<ARCH>::crc_query(uint64_t addr, size_t len, uint32_t& val) { return NotSupported; }
template <typename ARCH> status riscv_target_adapter<ARCH>::crc_query(uint64_t addr, size_t len, uint32_t &val) {
return NotSupported;
}
template <typename ARCH> status riscv_target_adapter<ARCH>::raw_query(std::string in_buf, std::string& out_buf) { return NotSupported; }
template <typename ARCH> status riscv_target_adapter<ARCH>::raw_query(std::string in_buf, std::string &out_buf) {
return NotSupported;
}
template <typename ARCH> status riscv_target_adapter<ARCH>::threadinfo_query(int first, std::string &out_buf) {
if (first) {
@ -306,7 +307,8 @@ template <typename ARCH> status riscv_target_adapter<ARCH>::threadinfo_query(int
return Ok;
}
template <typename ARCH> status riscv_target_adapter<ARCH>::threadextrainfo_query(const rp_thread_ref& thread, std::string& out_buf) {
template <typename ARCH>
status riscv_target_adapter<ARCH>::threadextrainfo_query(const rp_thread_ref &thread, std::string &out_buf) {
std::array<char, 20> 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);
@ -319,43 +321,30 @@ template <typename ARCH> status riscv_target_adapter<ARCH>::packetsize_query(std
return Ok;
}
template <typename ARCH> status riscv_target_adapter<ARCH>::add_break(break_type type, uint64_t addr, unsigned int length) {
switch(type) {
default:
return Err;
case SW_EXEC:
case HW_EXEC: {
template <typename ARCH> status riscv_target_adapter<ARCH>::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);
CPPLOG(TRACE) << "Adding breakpoint with handle " << target_adapter_base::bp_count << " for addr 0x" << std::hex << saddr.val
<< std::dec;
CPPLOG(TRACE) << "Now having " << target_adapter_base::bp_lut.size() << " breakpoints";
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 <typename ARCH> status riscv_target_adapter<ARCH>::remove_break(break_type type, uint64_t addr, unsigned int length) {
switch(type) {
default:
return Err;
case SW_EXEC:
case HW_EXEC: {
template <typename ARCH> status riscv_target_adapter<ARCH>::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) {
CPPLOG(TRACE) << "Removing breakpoint with handle " << handle << " for addr 0x" << std::hex << saddr.val << std::dec;
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);
CPPLOG(TRACE) << "Now having " << target_adapter_base::bp_lut.size() << " breakpoints";
LOG(TRACE) << "Now having " << target_adapter_base::bp_lut.size() << " breakpoints";
return Ok;
}
CPPLOG(TRACE) << "Now having " << target_adapter_base::bp_lut.size() << " breakpoints";
LOG(TRACE) << "Now having " << target_adapter_base::bp_lut.size() << " breakpoints";
return Err;
}
}
}
template <typename ARCH>
status riscv_target_adapter<ARCH>::resume_from_addr(bool step, int sig, uint64_t addr, rp_thread_ref thread,
@ -455,7 +444,7 @@ template <typename ARCH> status riscv_target_adapter<ARCH>::target_xml_query(std
</target>
*/
} // namespace debugger
} // namespace iss
}
}
#endif /* _ISS_DEBUGGER_RISCV_TARGET_ADAPTER_H_ */

View File

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (C) 2017 - 2023, MINRES Technologies GmbH
* Copyright (C) 2017, 2018, MINRES Technologies GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -37,23 +37,25 @@
#include "iss/instrumentation_if.h"
#include "iss/vm_plugin.h"
#include <functional>
#include <json/json.h>
#include <string>
#include <unordered_map>
#include <vector>
namespace iss {
namespace plugin {
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<unsigned(uint64_t)> f;
};
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(size, 0, 16)
instr_desc(uint32_t size, uint32_t taken, uint32_t not_taken): instr_desc() {
this->size=size;
this->taken=taken;
this->not_taken=not_taken;
}
END_BF_DECL();
public:
cycle_estimate() = delete;
@ -62,7 +64,7 @@ public:
cycle_estimate(const cycle_estimate &&) = delete;
cycle_estimate(std::string const& config_file_name);
cycle_estimate(std::string config_file_name);
virtual ~cycle_estimate();
@ -72,16 +74,13 @@ public:
bool registration(const char *const version, vm_if &arch) override;
sync_type get_sync() override { return ALL_SYNC; };
sync_type get_sync() override { return POST_SYNC; };
void callback(instr_info_t instr_info) override;
private:
iss::instrumentation_if* instr_if{nullptr};
uint32_t* reg_base_ptr{nullptr};
instr_desc illegal_desc{};
iss::instrumentation_if *arch_instr;
std::vector<instr_desc> delays;
unsigned current_delay{0};
struct pair_hash {
size_t operator()(const std::pair<uint64_t, uint64_t> &p) const {
std::hash<uint64_t> hash;
@ -89,9 +88,9 @@ private:
}
};
std::unordered_map<std::pair<uint64_t, uint64_t>, uint64_t, pair_hash> blocks;
std::string config_file_name;
Json::Value root;
};
} // namespace plugin
} // namespace iss
}
}
#endif /* _ISS_PLUGIN_CYCLE_ESTIMATE_H_ */

View File

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (C) 2017 - 2023, MINRES Technologies GmbH
* Copyright (C) 2017, 2018, MINRES Technologies GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -36,8 +36,8 @@
#define _ISS_PLUGIN_INSTRUCTION_COUNTER_H_
#include <iss/vm_plugin.h>
#include <json/json.h>
#include <string>
#include <vector>
namespace iss {
namespace plugin {
@ -69,13 +69,14 @@ public:
sync_type get_sync() override { return POST_SYNC; };
void callback(instr_info_t) override;
void callback(instr_info_t instr_info) override;
private:
Json::Value root;
std::vector<instr_delay> delays;
std::vector<uint64_t> rep_counts;
};
} // namespace plugin
} // namespace iss
}
}
#endif /* _ISS_PLUGIN_INSTRUCTION_COUNTER_H_ */

162
incl/sysc/core_complex.h Normal file
View File

@ -0,0 +1,162 @@
/*******************************************************************************
* Copyright (C) 2017, 2018 MINRES Technologies GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*******************************************************************************/
#ifndef _SYSC_SIFIVE_FE310_H_
#define _SYSC_SIFIVE_FE310_H_
#include "scc/initiator_mixin.h"
#include "scc/traceable.h"
#include "scc/utilities.h"
#include "scv4tlm/tlm_rec_initiator_socket.h"
#include <cci_configuration>
#include <tlm>
#include <tlm_core/tlm_1/tlm_req_rsp/tlm_1_interfaces/tlm_core_ifs.h>
#include <tlm_utils/tlm_quantumkeeper.h>
#include <util/range_lut.h>
class scv_tr_db;
class scv_tr_stream;
struct _scv_tr_generator_default_data;
template <class T_begin, class T_end> class scv_tr_generator;
namespace iss {
class vm_if;
namespace arch {
template <typename BASE> class riscv_hart_msu_vp;
}
namespace debugger {
class target_adapter_if;
}
}
namespace sysc {
class tlm_dmi_ext : public tlm::tlm_dmi {
public:
bool operator==(const tlm_dmi_ext &o) const {
return this->get_granted_access() == o.get_granted_access() &&
this->get_start_address() == o.get_start_address() && this->get_end_address() == o.get_end_address();
}
bool operator!=(const tlm_dmi_ext &o) const { return !operator==(o); }
};
namespace SiFive {
class core_wrapper;
class core_complex : public sc_core::sc_module, public scc::traceable {
public:
scc::initiator_mixin<scv4tlm::tlm_rec_initiator_socket<32>> initiator;
sc_core::sc_in<sc_core::sc_time> clk_i;
sc_core::sc_in<bool> rst_i;
sc_core::sc_in<bool> global_irq_i;
sc_core::sc_in<bool> timer_irq_i;
sc_core::sc_in<bool> sw_irq_i;
sc_core::sc_vector<sc_core::sc_in<bool>> local_irq_i;
sc_core::sc_port<tlm::tlm_peek_if<uint64_t>, 1, sc_core::SC_ZERO_OR_MORE_BOUND> mtime_o;
cci::cci_param<std::string> elf_file;
cci::cci_param<bool> enable_disass;
cci::cci_param<uint64_t> reset_address;
cci::cci_param<unsigned short> gdb_server_port;
cci::cci_param<bool> dump_ir;
core_complex(sc_core::sc_module_name name);
~core_complex();
inline void sync(uint64_t cycle) {
auto time = curr_clk * (cycle - last_sync_cycle);
quantum_keeper.inc(time);
if (quantum_keeper.need_sync()) {
wait(quantum_keeper.get_local_time());
quantum_keeper.reset();
}
last_sync_cycle = cycle;
}
bool read_mem(uint64_t addr, unsigned length, uint8_t *const data, bool is_fetch);
bool write_mem(uint64_t addr, unsigned length, const uint8_t *const data);
bool read_mem_dbg(uint64_t addr, unsigned length, uint8_t *const data);
bool write_mem_dbg(uint64_t addr, unsigned length, const uint8_t *const data);
void trace(sc_core::sc_trace_file *trf) const override;
void disass_output(uint64_t pc, const std::string instr);
protected:
void before_end_of_elaboration() override;
void start_of_simulation() override;
void run();
void clk_cb();
void rst_cb();
void sw_irq_cb();
void timer_irq_cb();
void global_irq_cb();
uint64_t last_sync_cycle = 0;
util::range_lut<tlm_dmi_ext> read_lut, write_lut;
tlm_utils::tlm_quantumkeeper quantum_keeper;
std::vector<uint8_t> write_buf;
std::unique_ptr<core_wrapper> cpu;
std::unique_ptr<iss::vm_if> vm;
sc_core::sc_time curr_clk;
iss::debugger::target_adapter_if *tgt_adapter;
#ifdef WITH_SCV
//! transaction recording database
scv_tr_db *m_db;
//! blocking transaction recording stream handle
scv_tr_stream *stream_handle;
//! transaction generator handle for blocking transactions
scv_tr_generator<_scv_tr_generator_default_data, _scv_tr_generator_default_data> *instr_tr_handle;
scv_tr_generator<uint64_t, _scv_tr_generator_default_data> *fetch_tr_handle;
scv_tr_handle tr_handle;
#endif
};
} /* namespace SiFive */
} /* namespace sysc */
#endif /* _SYSC_SIFIVE_FE310_H_ */

View File

@ -2,17 +2,31 @@ cmake_minimum_required(VERSION 3.12)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/../cmake) # main (top) cmake dir
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake) # project specific cmake dir
# CMake useful variables
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin")
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib")
# Set the name of your project here
project("sotfloat" VERSION 3.0.0)
project("sotfloat")
# Set the version number of your project here (format is MAJOR.MINOR.PATCHLEVEL - e.g. 1.0.0)
set(VERSION "3e")
#include(Common)
include(GNUInstallDirs)
include(Common)
set(SPECIALIZATION RISCV)
add_definitions(
-DSOFTFLOAT_ROUND_ODD
-DINLINE_LEVEL=5
-DSOFTFLOAT_FAST_DIV32TO16
-DSOFTFLOAT_FAST_DIV64TO32
-DSOFTFLOAT_FAST_INT64
# -DTHREAD_LOCAL=__thread
)
set(LIB_HEADERS source/include/softfloat.h source/include/softfloat_types.h)
set(PRIMITIVES
source/s_eq128.c
@ -327,29 +341,32 @@ set(OTHERS
set(LIB_SOURCES ${PRIMITIVES} ${SPECIALIZE} ${OTHERS})
add_library(softfloat STATIC ${LIB_SOURCES})
set_property(TARGET softfloat PROPERTY C_STANDARD 99)
target_compile_definitions(softfloat PRIVATE
SOFTFLOAT_ROUND_ODD
INLINE_LEVEL=5
SOFTFLOAT_FAST_DIV32TO16
SOFTFLOAT_FAST_DIV64TO32
SOFTFLOAT_FAST_INT64
# THREAD_LOCAL=__thread
)
target_include_directories(softfloat PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/build/Linux-x86_64-GCC)
target_include_directories(softfloat PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/source/include ${CMAKE_CURRENT_SOURCE_DIR}/source/${SPECIALIZATION})
set_target_properties(softfloat PROPERTIES
# Define two variables in order not to repeat ourselves.
set(LIBRARY_NAME softfloat)
# Define the library
add_library(${LIBRARY_NAME} ${LIB_SOURCES})
set_property(TARGET ${LIBRARY_NAME} PROPERTY C_STANDARD 99)
target_include_directories(${LIBRARY_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/build/Linux-x86_64-GCC)
target_include_directories(${LIBRARY_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/source/include ${CMAKE_CURRENT_SOURCE_DIR}/source/${SPECIALIZATION})
# Set the build version. It will be used in the name of the lib, with corresponding
# symlinks created. SOVERSION could also be specified for api version.
set_target_properties(${LIBRARY_NAME} PROPERTIES
VERSION ${VERSION}
FRAMEWORK FALSE
PUBLIC_HEADER "${LIB_HEADERS}"
)
install(TARGETS softfloat
# Says how and where to install software
# Targets:
# * <prefix>/lib/<libraries>
# * header location after install: <prefix>/include/<project>/*.h
# * headers can be included by C++ code `#<project>/Bar.hpp>`
install(TARGETS ${LIBRARY_NAME}
EXPORT ${PROJECT_NAME}Targets # for downstream dependencies
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}/static COMPONENT libs # static lib
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT libs # shared lib
FRAMEWORK DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT libs # for mac
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} COMPONENT devel # headers for mac (note the different component -> different package)
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} # headers
ARCHIVE DESTINATION lib COMPONENT libs # static lib
LIBRARY DESTINATION lib COMPONENT libs # shared lib
FRAMEWORK DESTINATION bin COMPONENT libs # for mac
PUBLIC_HEADER DESTINATION include COMPONENT devel # headers for mac (note the different component -> different package)
INCLUDES DESTINATION include # headers
)

View File

@ -50,3 +50,4 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*----------------------------------------------------------------------------*/
#define SOFTFLOAT_BUILTIN_CLZ 1
#include "opts-GCC.h"

View File

@ -50,3 +50,4 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*----------------------------------------------------------------------------*/
#define SOFTFLOAT_BUILTIN_CLZ 1
#include "opts-GCC.h"

View File

@ -50,3 +50,4 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*----------------------------------------------------------------------------*/
#define SOFTFLOAT_BUILTIN_CLZ 1
#include "opts-GCC.h"

View File

@ -49,8 +49,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/*----------------------------------------------------------------------------
*----------------------------------------------------------------------------*/
#ifdef __GNUC__
#define SOFTFLOAT_BUILTIN_CLZ 1
#define SOFTFLOAT_INTRINSIC_INT128 1
#endif
#include "opts-GCC.h"

View File

@ -50,3 +50,4 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*----------------------------------------------------------------------------*/
#define SOFTFLOAT_BUILTIN_CLZ 1
#include "opts-GCC.h"

View File

@ -50,3 +50,4 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*----------------------------------------------------------------------------*/
#define SOFTFLOAT_BUILTIN_CLZ 1
#include "opts-GCC.h"

View File

@ -51,3 +51,4 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define SOFTFLOAT_BUILTIN_CLZ 1
#define SOFTFLOAT_INTRINSIC_INT128 1
#include "opts-GCC.h"

View File

@ -47,3 +47,4 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/*----------------------------------------------------------------------------
*----------------------------------------------------------------------------*/
==> #define THREAD_LOCAL _Thread_local

View File

@ -47,3 +47,4 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/*----------------------------------------------------------------------------
*----------------------------------------------------------------------------*/
==> #define THREAD_LOCAL _Thread_local

View File

@ -37,10 +37,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef specialize_h
#define specialize_h 1
#include "primitiveTypes.h"
#include "softfloat.h"
#include <stdbool.h>
#include <stdint.h>
#include "primitiveTypes.h"
#include "softfloat.h"
/*----------------------------------------------------------------------------
| Default value for 'softfloat_detectTininess'.
@ -114,7 +114,8 @@ 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.
@ -148,7 +149,8 @@ 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.
@ -160,8 +162,7 @@ uint_fast32_t softfloat_propagateNaNF32UI(uint_fast32_t uiA, uint_fast32_t uiB);
| 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
@ -183,7 +184,8 @@ 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.
@ -197,8 +199,7 @@ uint_fast64_t softfloat_propagateNaNF64UI(uint_fast64_t uiA, uint_fast64_t uiB);
| 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
@ -214,7 +215,9 @@ uint_fast64_t softfloat_propagateNaNF64UI(uint_fast64_t uiA, uint_fast64_t uiB);
| 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
@ -232,7 +235,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.
@ -246,8 +255,7 @@ struct uint128 softfloat_propagateNaNExtF80UI(uint_fast16_t uiA64, uint_fast64_t
| 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'
@ -256,7 +264,9 @@ struct uint128 softfloat_propagateNaNExtF80UI(uint_fast16_t uiA64, uint_fast64_t
| 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
@ -273,7 +283,13 @@ 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
@ -288,14 +304,18 @@ struct uint128 softfloat_propagateNaNF128UI(uint_fast64_t uiA64, uint_fast64_t u
| 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
@ -303,7 +323,12 @@ void softfloat_commonNaNToExtF80M(const struct commonNaN* aPtr, struct extFloat8
| 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.
@ -321,7 +346,8 @@ void softfloat_propagateNaNExtF80M(const struct extFloat80M* aSPtr, const struct
| 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
@ -329,7 +355,8 @@ void softfloat_f128MToCommonNaN(const uint32_t* aWPtr, struct commonNaN* zPtr);
| '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
@ -339,8 +366,11 @@ void softfloat_commonNaNToF128M(const struct commonNaN* aPtr, uint32_t* zWPtr);
| 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

View File

@ -37,10 +37,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef specialize_h
#define specialize_h 1
#include "primitiveTypes.h"
#include "softfloat.h"
#include <stdbool.h>
#include <stdint.h>
#include "primitiveTypes.h"
#include "softfloat.h"
/*----------------------------------------------------------------------------
| Default value for 'softfloat_detectTininess'.
@ -114,7 +114,8 @@ 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.
@ -148,7 +149,8 @@ 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.
@ -160,8 +162,7 @@ uint_fast32_t softfloat_propagateNaNF32UI(uint_fast32_t uiA, uint_fast32_t uiB);
| 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
@ -183,7 +184,8 @@ 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.
@ -197,8 +199,7 @@ uint_fast64_t softfloat_propagateNaNF64UI(uint_fast64_t uiA, uint_fast64_t uiB);
| 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
@ -214,7 +215,9 @@ uint_fast64_t softfloat_propagateNaNF64UI(uint_fast64_t uiA, uint_fast64_t uiB);
| 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
@ -232,7 +235,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.
@ -246,8 +255,7 @@ struct uint128 softfloat_propagateNaNExtF80UI(uint_fast16_t uiA64, uint_fast64_t
| 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'
@ -256,7 +264,9 @@ struct uint128 softfloat_propagateNaNExtF80UI(uint_fast16_t uiA64, uint_fast64_t
| 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
@ -273,7 +283,13 @@ 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
@ -288,14 +304,18 @@ struct uint128 softfloat_propagateNaNF128UI(uint_fast64_t uiA64, uint_fast64_t u
| 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
@ -303,7 +323,12 @@ void softfloat_commonNaNToExtF80M(const struct commonNaN* aPtr, struct extFloat8
| 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.
@ -321,7 +346,8 @@ void softfloat_propagateNaNExtF80M(const struct extFloat80M* aSPtr, const struct
| 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
@ -329,7 +355,8 @@ void softfloat_f128MToCommonNaN(const uint32_t* aWPtr, struct commonNaN* zPtr);
| '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
@ -339,8 +366,11 @@ void softfloat_commonNaNToF128M(const struct commonNaN* aPtr, uint32_t* zWPtr);
| 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

View File

@ -37,10 +37,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef specialize_h
#define specialize_h 1
#include "primitiveTypes.h"
#include "softfloat.h"
#include <stdbool.h>
#include <stdint.h>
#include "primitiveTypes.h"
#include "softfloat.h"
/*----------------------------------------------------------------------------
| Default value for 'softfloat_detectTininess'.
@ -73,9 +73,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
| "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.
@ -95,9 +93,7 @@ struct commonNaN {
| 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
@ -111,7 +107,8 @@ struct commonNaN {
| 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.
@ -131,9 +128,7 @@ uint_fast16_t softfloat_propagateNaNF16UI(uint_fast16_t uiA, uint_fast16_t uiB);
| 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
@ -147,7 +142,8 @@ uint_fast16_t softfloat_propagateNaNF16UI(uint_fast16_t uiA, uint_fast16_t uiB);
| 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.
@ -159,8 +155,7 @@ uint_fast32_t softfloat_propagateNaNF32UI(uint_fast32_t uiA, uint_fast32_t uiB);
| 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
@ -168,9 +163,7 @@ uint_fast32_t softfloat_propagateNaNF32UI(uint_fast32_t uiA, uint_fast32_t uiB);
| 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
@ -184,7 +177,8 @@ uint_fast32_t softfloat_propagateNaNF32UI(uint_fast32_t uiA, uint_fast32_t uiB);
| 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.
@ -198,8 +192,7 @@ uint_fast64_t softfloat_propagateNaNF64UI(uint_fast64_t uiA, uint_fast64_t uiB);
| 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,9 +208,7 @@ uint_fast64_t softfloat_propagateNaNF64UI(uint_fast64_t uiA, uint_fast64_t uiB);
| 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
@ -226,7 +217,8 @@ uint_fast64_t softfloat_propagateNaNF64UI(uint_fast64_t uiA, uint_fast64_t uiB);
*----------------------------------------------------------------------------*/
#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;
@ -245,7 +237,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.
@ -259,8 +257,7 @@ struct uint128 softfloat_propagateNaNExtF80UI(uint_fast16_t uiA64, uint_fast64_t
| 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'
@ -269,9 +266,7 @@ struct uint128 softfloat_propagateNaNExtF80UI(uint_fast16_t uiA64, uint_fast64_t
| 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
@ -279,7 +274,8 @@ struct uint128 softfloat_propagateNaNExtF80UI(uint_fast16_t uiA64, uint_fast64_t
*----------------------------------------------------------------------------*/
#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;
@ -298,7 +294,13 @@ 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
@ -313,9 +315,7 @@ struct uint128 softfloat_propagateNaNF128UI(uint_fast64_t uiA64, uint_fast64_t u
| 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
@ -324,12 +324,17 @@ struct uint128 softfloat_propagateNaNF128UI(uint_fast64_t uiA64, uint_fast64_t u
*----------------------------------------------------------------------------*/
#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;
}
#else
void softfloat_commonNaNToExtF80M(const struct commonNaN* aPtr, struct extFloat80M* zSPtr);
void
softfloat_commonNaNToExtF80M(
const struct commonNaN *aPtr, struct extFloat80M *zSPtr );
#endif
/*----------------------------------------------------------------------------
@ -338,7 +343,12 @@ void softfloat_commonNaNToExtF80M(const struct commonNaN* aPtr, struct extFloat8
| 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,9 +366,7 @@ void softfloat_propagateNaNExtF80M(const struct extFloat80M* aSPtr, const struct
| 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
@ -368,14 +376,17 @@ void softfloat_propagateNaNExtF80M(const struct extFloat80M* aSPtr, const struct
*----------------------------------------------------------------------------*/
#if defined INLINE && ! defined softfloat_commonNaNToF128M
INLINE
void softfloat_commonNaNToF128M(const struct commonNaN* aPtr, uint32_t* zWPtr) {
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
/*----------------------------------------------------------------------------
@ -386,8 +397,11 @@ void softfloat_commonNaNToF128M(const struct commonNaN* aPtr, uint32_t* zWPtr);
| 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

View File

@ -37,10 +37,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef specialize_h
#define specialize_h 1
#include "primitiveTypes.h"
#include "softfloat.h"
#include <stdbool.h>
#include <stdint.h>
#include "primitiveTypes.h"
#include "softfloat.h"
/*----------------------------------------------------------------------------
| Default value for 'softfloat_detectTininess'.
@ -114,7 +114,8 @@ 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.
@ -148,7 +149,8 @@ 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.
@ -160,8 +162,7 @@ uint_fast32_t softfloat_propagateNaNF32UI(uint_fast32_t uiA, uint_fast32_t uiB);
| 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
@ -183,7 +184,8 @@ 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.
@ -197,8 +199,7 @@ uint_fast64_t softfloat_propagateNaNF64UI(uint_fast64_t uiA, uint_fast64_t uiB);
| 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
@ -214,7 +215,9 @@ uint_fast64_t softfloat_propagateNaNF64UI(uint_fast64_t uiA, uint_fast64_t uiB);
| 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
@ -232,7 +235,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.
@ -246,8 +255,7 @@ struct uint128 softfloat_propagateNaNExtF80UI(uint_fast16_t uiA64, uint_fast64_t
| 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'
@ -256,7 +264,9 @@ struct uint128 softfloat_propagateNaNExtF80UI(uint_fast16_t uiA64, uint_fast64_t
| 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
@ -273,7 +283,13 @@ 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
@ -288,14 +304,18 @@ struct uint128 softfloat_propagateNaNF128UI(uint_fast64_t uiA64, uint_fast64_t u
| 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
@ -303,7 +323,12 @@ void softfloat_commonNaNToExtF80M(const struct commonNaN* aPtr, struct extFloat8
| 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.
@ -321,7 +346,8 @@ void softfloat_propagateNaNExtF80M(const struct extFloat80M* aSPtr, const struct
| 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
@ -329,7 +355,8 @@ void softfloat_f128MToCommonNaN(const uint32_t* aWPtr, struct commonNaN* zPtr);
| '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
@ -339,8 +366,11 @@ void softfloat_commonNaNToF128M(const struct commonNaN* aPtr, uint32_t* zWPtr);
| 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

View File

@ -37,10 +37,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef specialize_h
#define specialize_h 1
#include "primitiveTypes.h"
#include "softfloat.h"
#include <stdbool.h>
#include <stdint.h>
#include "primitiveTypes.h"
#include "softfloat.h"
/*----------------------------------------------------------------------------
| Default value for 'softfloat_detectTininess'.
@ -114,7 +114,8 @@ 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.
@ -148,7 +149,8 @@ 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.
@ -160,8 +162,7 @@ uint_fast32_t softfloat_propagateNaNF32UI(uint_fast32_t uiA, uint_fast32_t uiB);
| 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
@ -183,7 +184,8 @@ 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.
@ -197,8 +199,7 @@ uint_fast64_t softfloat_propagateNaNF64UI(uint_fast64_t uiA, uint_fast64_t uiB);
| 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
@ -214,7 +215,9 @@ uint_fast64_t softfloat_propagateNaNF64UI(uint_fast64_t uiA, uint_fast64_t uiB);
| 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
@ -232,7 +235,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.
@ -246,8 +255,7 @@ struct uint128 softfloat_propagateNaNExtF80UI(uint_fast16_t uiA64, uint_fast64_t
| 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'
@ -256,7 +264,9 @@ struct uint128 softfloat_propagateNaNExtF80UI(uint_fast16_t uiA64, uint_fast64_t
| 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
@ -273,7 +283,13 @@ 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
@ -288,14 +304,18 @@ struct uint128 softfloat_propagateNaNF128UI(uint_fast64_t uiA64, uint_fast64_t u
| 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
@ -303,7 +323,12 @@ void softfloat_commonNaNToExtF80M(const struct commonNaN* aPtr, struct extFloat8
| 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.
@ -321,7 +346,8 @@ void softfloat_propagateNaNExtF80M(const struct extFloat80M* aSPtr, const struct
| 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
@ -329,7 +355,8 @@ void softfloat_f128MToCommonNaN(const uint32_t* aWPtr, struct commonNaN* zPtr);
| '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
@ -339,8 +366,11 @@ void softfloat_commonNaNToF128M(const struct commonNaN* aPtr, uint32_t* zWPtr);
| 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

View File

@ -37,43 +37,33 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef internals_h
#define internals_h 1
#include "primitives.h"
#include "softfloat_types.h"
#include <stdbool.h>
#include <stdint.h>
#include "primitives.h"
#include "softfloat_types.h"
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;
};
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;
};
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 };
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
uint_fast64_t softfloat_roundToUI64(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
uint_fast64_t softfloat_roundMToUI64( bool, uint32_t *, uint_fast8_t, bool );
#endif
@ -81,7 +71,9 @@ uint_fast64_t softfloat_roundMToUI64(bool, uint32_t*, uint_fast8_t, bool);
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);
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
@ -95,10 +87,7 @@ int_fast64_t softfloat_roundMToI64(bool, uint32_t*, uint_fast8_t, bool);
#define isNaNF16UI( a ) (((~(a) & 0x7C00) == 0) && ((a) & 0x03FF))
struct exp8_sig16 {
int_fast8_t exp;
uint_fast16_t sig;
};
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 );
@ -106,7 +95,9 @@ 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_mulAddF16(
uint_fast16_t, uint_fast16_t, uint_fast16_t, uint_fast8_t );
/*----------------------------------------------------------------------------
*----------------------------------------------------------------------------*/
@ -117,10 +108,7 @@ float16_t softfloat_mulAddF16(uint_fast16_t, uint_fast16_t, uint_fast16_t, uint_
#define isNaNF32UI( a ) (((~(a) & 0x7F800000) == 0) && ((a) & 0x007FFFFF))
struct exp16_sig32 {
int_fast16_t exp;
uint_fast32_t sig;
};
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 );
@ -128,7 +116,9 @@ 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_mulAddF32(
uint_fast32_t, uint_fast32_t, uint_fast32_t, uint_fast8_t );
/*----------------------------------------------------------------------------
*----------------------------------------------------------------------------*/
@ -139,10 +129,7 @@ float32_t softfloat_mulAddF32(uint_fast32_t, uint_fast32_t, uint_fast32_t, uint_
#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 { 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 );
@ -150,7 +137,9 @@ 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_mulAddF64(
uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast8_t );
/*----------------------------------------------------------------------------
*----------------------------------------------------------------------------*/
@ -165,17 +154,22 @@ float64_t softfloat_mulAddF64(uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_
/*----------------------------------------------------------------------------
*----------------------------------------------------------------------------*/
struct exp32_sig64 {
int_fast32_t exp;
uint64_t sig;
};
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 );
/*----------------------------------------------------------------------------
*----------------------------------------------------------------------------*/
@ -186,35 +180,67 @@ extFloat80_t softfloat_subMagsExtF80(uint_fast16_t, uint_fast64_t, uint_fast16_t
#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*);
bool
softfloat_tryPropagateNaNExtF80M(
const struct extFloat80M *,
const struct extFloat80M *,
struct extFloat80M *
);
void softfloat_invalidExtF80M( struct extFloat80M * );
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 * );
/*----------------------------------------------------------------------------
*----------------------------------------------------------------------------*/
@ -225,7 +251,9 @@ int softfloat_compareNonnormExtF80M(const struct extFloat80M*, const struct extF
bool softfloat_isNaNF128M( const uint32_t * );
bool softfloat_tryPropagateNaNF128M(const uint32_t*, const uint32_t*, 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 * );
@ -233,9 +261,18 @@ 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_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

View File

@ -39,57 +39,57 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifdef INLINE
#include "primitiveTypes.h"
#include <stdint.h>
#include "primitiveTypes.h"
#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;
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;
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;
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;
@ -111,3 +111,4 @@ void softfloat_mul128To256M(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0
#endif
#endif

View File

@ -42,27 +42,13 @@ 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
@ -81,8 +67,7 @@ struct uint128_extra {
#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 INIT_UINTM4( v3, v2, v1, v0 ) { v0, v1, v2, v3 }
#else
#define wordIncr -1
#define indexWord( total, n ) ((total) - 1 - (n))
@ -93,8 +78,8 @@ struct uint128_extra {
#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 INIT_UINTM4( v3, v2, v1, v0 ) { v3, v2, v1, v0 }
#endif
#endif

View File

@ -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 <stdbool.h>
#include <stdint.h>
#include "primitiveTypes.h"
#ifndef softfloat_shortShiftRightJam64
/*----------------------------------------------------------------------------
@ -50,7 +50,8 @@ 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) - 1)) != 0); }
uint64_t softfloat_shortShiftRightJam64( uint64_t a, uint_fast8_t dist )
{ return a>>dist | ((a & (((uint_fast64_t) 1<<dist) - 1)) != 0); }
#else
uint64_t softfloat_shortShiftRightJam64( uint64_t a, uint_fast8_t dist );
#endif
@ -67,8 +68,10 @@ 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 );
@ -86,8 +89,10 @@ 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 );
@ -107,7 +112,8 @@ 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 ) {
count = 0;
@ -127,7 +133,8 @@ 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 ) {
count = 16;
@ -215,7 +222,8 @@ 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 );
#endif
@ -229,7 +237,8 @@ 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 );
#endif
@ -243,7 +252,8 @@ 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 );
#endif
@ -256,14 +266,17 @@ 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 | 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
@ -274,14 +287,17 @@ struct uint128 softfloat_shortShiftLeft128(uint64_t a64, uint64_t a0, uint_fast8
*----------------------------------------------------------------------------*/
#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;
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
@ -292,14 +308,19 @@ struct uint128 softfloat_shortShiftRight128(uint64_t a64, uint64_t a0, uint_fast
*----------------------------------------------------------------------------*/
#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);
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
@ -313,15 +334,22 @@ struct uint64_extra softfloat_shortShiftRightJam64Extra(uint64_t a, uint64_t ext
*----------------------------------------------------------------------------*/
#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.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
@ -332,7 +360,10 @@ struct uint128 softfloat_shortShiftRightJam128(uint64_t a64, uint64_t a0, uint_f
*----------------------------------------------------------------------------*/
#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;
@ -341,7 +372,9 @@ struct uint128_extra softfloat_shortShiftRightJam128Extra(uint64_t a64, uint64_t
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
@ -364,7 +397,10 @@ struct uint128_extra softfloat_shortShiftRightJam128Extra(uint64_t a64, uint64_t
*----------------------------------------------------------------------------*/
#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;
@ -377,7 +413,9 @@ struct uint64_extra softfloat_shiftRightJam64Extra(uint64_t a, uint64_t extra, u
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
@ -392,7 +430,8 @@ struct uint64_extra softfloat_shiftRightJam64Extra(uint64_t a, uint64_t extra, u
| 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
@ -413,7 +452,9 @@ struct uint128 softfloat_shiftRightJam128(uint64_t a64, uint64_t a0, uint_fast32
| 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
@ -429,7 +470,9 @@ struct uint128_extra softfloat_shiftRightJam128Extra(uint64_t a64, uint64_t a0,
| 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
@ -440,14 +483,17 @@ void softfloat_shiftRightJam256M(const uint64_t* aPtr, uint_fast32_t dist, uint6
*----------------------------------------------------------------------------*/
#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
@ -459,7 +505,9 @@ struct uint128 softfloat_add128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_
| 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
@ -470,7 +518,9 @@ void softfloat_add256M(const uint64_t* aPtr, const uint64_t* bPtr, uint64_t* zPt
*----------------------------------------------------------------------------*/
#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;
@ -478,7 +528,8 @@ struct uint128 softfloat_sub128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_
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
@ -491,7 +542,9 @@ struct uint128 softfloat_sub128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_
| 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
@ -499,7 +552,8 @@ void softfloat_sub256M(const uint64_t* aPtr, const uint64_t* bPtr, uint64_t* zPt
| 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;
@ -527,7 +581,8 @@ 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;
@ -550,7 +605,9 @@ 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
@ -581,7 +638,8 @@ 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
@ -594,14 +652,19 @@ int_fast8_t softfloat_compare128M(const uint32_t* aPtr, const uint32_t* bPtr);
*----------------------------------------------------------------------------*/
#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
INLINE
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 )
{
zPtr[indexWord( 3, 0 )] = (uint32_t) a<<dist;
a >>= 32 - dist;
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
@ -615,7 +678,13 @@ void softfloat_shortShiftLeft64To96M(uint64_t a, uint_fast8_t dist, uint32_t* zP
| 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
@ -653,7 +722,13 @@ void softfloat_shortShiftLeftM(uint_fast8_t size_words, const uint32_t* aPtr, ui
| 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
@ -690,7 +765,13 @@ void softfloat_shiftLeftM(uint_fast8_t size_words, const uint32_t* aPtr, uint32_
| 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
@ -720,7 +801,9 @@ void softfloat_shortShiftRightM(uint_fast8_t size_words, const uint32_t* aPtr, u
| 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
@ -742,7 +825,13 @@ void softfloat_shortShiftRightJamM(uint_fast8_t, const uint32_t*, uint_fast8_t,
| 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
@ -767,7 +856,13 @@ void softfloat_shiftRightM(uint_fast8_t size_words, const uint32_t* aPtr, uint32
| 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
@ -803,7 +898,13 @@ void softfloat_shiftRightJamM(uint_fast8_t size_words, const uint32_t* aPtr, uin
| 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
@ -839,7 +940,14 @@ void softfloat_addM(uint_fast8_t size_words, const uint32_t* aPtr, const uint32_
| 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
@ -848,8 +956,14 @@ uint_fast8_t softfloat_addCarryM(uint_fast8_t size_words, const uint32_t* aPtr,
| 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
@ -938,7 +1052,13 @@ 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
@ -984,7 +1104,9 @@ 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
@ -997,8 +1119,15 @@ void softfloat_mul128MTo256M(const uint32_t* aPtr, const uint32_t* bPtr, uint32_
| 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
@ -1028,3 +1157,4 @@ void softfloat_remStepMBy32(uint_fast8_t size_words, const uint32_t* remPtr, uin
#endif
#endif

View File

@ -34,6 +34,7 @@ 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
@ -41,12 +42,13 @@ 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 <stdbool.h>
#include <stdint.h>
#include "softfloat_types.h"
#ifndef THREAD_LOCAL
#define THREAD_LOCAL
@ -56,7 +58,10 @@ 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
@ -283,7 +288,9 @@ 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_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 * );
@ -346,7 +353,10 @@ 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_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 * );
@ -359,3 +369,4 @@ bool f128M_lt_quiet(const float128_t*, const float128_t*);
bool f128M_isSignalingNaN( const float128_t * );
#endif

View File

@ -47,18 +47,10 @@ 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
@ -66,15 +58,9 @@ typedef struct {
| 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
/*----------------------------------------------------------------------------
@ -92,3 +78,4 @@ struct extFloat80M {
typedef struct extFloat80M extFloat80_t;
#endif

3
src-gen/.gitignore vendored
View File

@ -1,3 +0,0 @@
/iss
/vm
/sysc

1
src/iss/.gitignore vendored
View File

@ -1 +0,0 @@
/tgc_*.cpp

View File

@ -1,122 +0,0 @@
/*******************************************************************************
* Copyright (C) 2022 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_HWL_H
#define _RISCV_HART_M_P_HWL_H
#include "riscv_hart_common.h"
#include <iss/vm_types.h>
namespace iss {
namespace arch {
template <typename BASE> class hwl : public BASE {
public:
using base_class = BASE;
using this_class = hwl<BASE>;
using reg_t = typename BASE::reg_t;
hwl(feature_config cfg = feature_config{});
virtual ~hwl() = default;
protected:
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 <typename BASE>
inline hwl<BASE>::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) {
this->register_custom_csr_rd(addr);
this->register_custom_csr_wr(addr);
}
}
template <typename BASE> inline iss::status iss::arch::hwl<BASE>::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 <typename BASE> inline iss::status iss::arch::hwl<BASE>::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;
}
} // namespace arch
} // namespace iss
#endif /* _RISCV_HART_M_P_H */

View File

@ -1,364 +0,0 @@
/*******************************************************************************
* Copyright (C) 2017, 2018, 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_COMMON
#define _RISCV_HART_COMMON
#include <cstdint>
#include <elfio/elfio.hpp>
#include <fmt/format.h>
#include <iss/arch_if.h>
#include <iss/log_categories.h>
#include <string>
#include <unordered_map>
#include <util/logging.h>
namespace iss {
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 riscv_csr {
/* user-level CSR */
// User Trap Setup
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,
fcsr = 0x003,
// User Counter/Timers
cycle = 0xC00,
time = 0xC01,
instret = 0xC02,
hpmcounter3 = 0xC03,
hpmcounter4 = 0xC04,
/*...*/
hpmcounter31 = 0xC1F,
cycleh = 0xC80,
timeh = 0xC81,
instreth = 0xC82,
hpmcounter3h = 0xC83,
hpmcounter4h = 0xC84,
/*...*/
hpmcounter31h = 0xC9F,
/* supervisor-level CSR */
// Supervisor Trap Setup
sstatus = 0x100,
sedeleg = 0x102,
sideleg = 0x103,
sie = 0x104,
stvec = 0x105,
scounteren = 0x106,
// Supervisor Trap Handling
sscratch = 0x140,
sepc = 0x141,
scause = 0x142,
stval = 0x143,
sip = 0x144,
// Supervisor Protection and Translation
satp = 0x180,
/* machine-level CSR */
// Machine Information Registers
mvendorid = 0xF11,
marchid = 0xF12,
mimpid = 0xF13,
mhartid = 0xF14,
// Machine Trap Setup
mstatus = 0x300,
misa = 0x301,
medeleg = 0x302,
mideleg = 0x303,
mie = 0x304,
mtvec = 0x305,
mcounteren = 0x306,
mtvt = 0x307, // CLIC
// Machine Trap Handling
mscratch = 0x340,
mepc = 0x341,
mcause = 0x342,
mtval = 0x343,
mip = 0x344,
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)
// Physical Memory Protection
pmpcfg0 = 0x3A0,
pmpcfg1 = 0x3A1,
pmpcfg2 = 0x3A2,
pmpcfg3 = 0x3A3,
pmpaddr0 = 0x3B0,
pmpaddr1 = 0x3B1,
pmpaddr2 = 0x3B2,
pmpaddr3 = 0x3B3,
pmpaddr4 = 0x3B4,
pmpaddr5 = 0x3B5,
pmpaddr6 = 0x3B6,
pmpaddr7 = 0x3B7,
pmpaddr8 = 0x3B8,
pmpaddr9 = 0x3B9,
pmpaddr10 = 0x3BA,
pmpaddr11 = 0x3BB,
pmpaddr12 = 0x3BC,
pmpaddr13 = 0x3BD,
pmpaddr14 = 0x3BE,
pmpaddr15 = 0x3BF,
// Machine Counter/Timers
mcycle = 0xB00,
minstret = 0xB02,
mhpmcounter3 = 0xB03,
mhpmcounter4 = 0xB04,
/*...*/
mhpmcounter31 = 0xB1F,
mcycleh = 0xB80,
minstreth = 0xB82,
mhpmcounter3h = 0xB83,
mhpmcounter4h = 0xB84,
/*...*/
mhpmcounter31h = 0xB9F,
// Machine Counter Setup
mhpmevent3 = 0x323,
mhpmevent4 = 0x324,
/*...*/
mhpmevent31 = 0x33F,
// Debug/Trace Registers (shared with Debug Mode)
tselect = 0x7A0,
tdata1 = 0x7A1,
tdata2 = 0x7A2,
tdata3 = 0x7A3,
// Debug Mode Registers
dcsr = 0x7B0,
dpc = 0x7B1,
dscratch0 = 0x7B2,
dscratch1 = 0x7B3
};
enum {
PGSHIFT = 12,
PTE_PPN_SHIFT = 10,
// page table entry (PTE) fields
PTE_V = 0x001, // Valid
PTE_R = 0x002, // Read
PTE_W = 0x004, // Write
PTE_X = 0x008, // Execute
PTE_U = 0x010, // User
PTE_G = 0x020, // Global
PTE_A = 0x040, // Accessed
PTE_D = 0x080, // Dirty
PTE_SOFT = 0x300 // Reserved for Software
};
template <typename T> 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 {
ISA_A = 1,
ISA_B = 1 << 1,
ISA_C = 1 << 2,
ISA_D = 1 << 3,
ISA_E = 1 << 4,
ISA_F = 1 << 5,
ISA_G = 1 << 6,
ISA_I = 1 << 8,
ISA_M = 1 << 12,
ISA_N = 1 << 13,
ISA_Q = 1 << 16,
ISA_S = 1 << 18,
ISA_U = 1 << 20
};
struct vm_info {
int levels;
int idxbits;
int ptesize;
uint64_t ptbase;
bool is_active() { return levels; }
};
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 {
public:
trap_load_access_fault(uint64_t badaddr)
: trap_access(5 << 16, badaddr) {}
};
class illegal_instruction_fault : public trap_access {
public:
illegal_instruction_fault(uint64_t badaddr)
: trap_access(2 << 16, badaddr) {}
};
class trap_instruction_page_fault : public trap_access {
public:
trap_instruction_page_fault(uint64_t badaddr)
: trap_access(12 << 16, badaddr) {}
};
class trap_load_page_fault : public trap_access {
public:
trap_load_page_fault(uint64_t badaddr)
: trap_access(13 << 16, badaddr) {}
};
class trap_store_page_fault : public trap_access {
public:
trap_store_page_fault(uint64_t badaddr)
: trap_access(15 << 16, badaddr) {}
};
inline void read_reg_uint32(uint64_t offs, uint32_t& reg, uint8_t* const data, unsigned length) {
auto reg_ptr = reinterpret_cast<uint8_t*>(&reg);
switch(offs & 0x3) {
case 0:
for(auto i = 0U; i < length; ++i)
*(data + i) = *(reg_ptr + i);
break;
case 1:
for(auto i = 0U; i < length; ++i)
*(data + i) = *(reg_ptr + 1 + i);
break;
case 2:
for(auto i = 0U; i < length; ++i)
*(data + i) = *(reg_ptr + 2 + i);
break;
case 3:
*data = *(reg_ptr + 3);
break;
}
}
inline void write_reg_uint32(uint64_t offs, uint32_t& reg, const uint8_t* const data, unsigned length) {
auto reg_ptr = reinterpret_cast<uint8_t*>(&reg);
switch(offs & 0x3) {
case 0:
for(auto i = 0U; i < length; ++i)
*(reg_ptr + i) = *(data + i);
break;
case 1:
for(auto i = 0U; i < length; ++i)
*(reg_ptr + 1 + i) = *(data + i);
break;
case 2:
for(auto i = 0U; i < length; ++i)
*(reg_ptr + 2 + i) = *(data + i);
break;
case 3:
*(reg_ptr + 3) = *data;
break;
}
}
struct riscv_hart_common {
riscv_hart_common(){};
~riscv_hart_common(){};
std::unordered_map<std::string, uint64_t> symbol_table;
std::unordered_map<std::string, uint64_t> get_sym_table(std::string name) {
if(!symbol_table.empty())
return symbol_table;
FILE* fp = fopen(name.c_str(), "r");
if(fp) {
std::array<char, 5> 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_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");
const auto sym_sec = reader.sections[".symtab"];
if(SHT_SYMTAB == sym_sec->get_type() || SHT_DYNSYM == sym_sec->get_type()) {
ELFIO::symbol_section_accessor symbols(reader, sym_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 != "") {
this->symbol_table[name] = value;
#ifndef NDEBUG
CPPLOG(DEBUG) << "Found Symbol " << name;
#endif
}
}
}
return symbol_table;
}
throw std::runtime_error(fmt::format("memory load file {} is not a valid elf file", name));
} else
throw std::runtime_error(fmt::format("memory load file not found, check if {} is a valid file", name));
};
};
} // namespace arch
} // namespace iss
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,263 +0,0 @@
/*******************************************************************************
* Copyright (C) 2017 - 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.
*
*******************************************************************************/
#ifndef _TGC5C_H_
#define _TGC5C_H_
// clang-format off
#include <array>
#include <iss/arch/traits.h>
#include <iss/arch_if.h>
#include <iss/vm_if.h>
namespace iss {
namespace arch {
struct tgc5c;
template <> struct traits<tgc5c> {
constexpr static char const* const core_type = "TGC5C";
static constexpr std::array<const char*, 36> 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"}};
static constexpr std::array<const char*, 36> 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"}};
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, INSTRUCTION, LAST_BRANCH
};
using reg_t = uint32_t;
using addr_t = uint32_t;
using code_word_t = uint32_t; //TODO: check removal
using virt_addr_t = iss::typed_addr_t<iss::address_type::VIRTUAL>;
using phys_addr_t = iss::typed_addr_t<iss::address_type::PHYSICAL>;
static constexpr std::array<const uint32_t, 43> 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<const uint32_t, 43> 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, FENCE, RES, CSR, IMEM = MEM };
enum class opcode_e {
LUI = 0,
AUIPC = 1,
JAL = 2,
JALR = 3,
BEQ = 4,
BNE = 5,
BLT = 6,
BGE = 7,
BLTU = 8,
BGEU = 9,
LB = 10,
LH = 11,
LW = 12,
LBU = 13,
LHU = 14,
SB = 15,
SH = 16,
SW = 17,
ADDI = 18,
SLTI = 19,
SLTIU = 20,
XORI = 21,
ORI = 22,
ANDI = 23,
SLLI = 24,
SRLI = 25,
SRAI = 26,
ADD = 27,
SUB = 28,
SLL = 29,
SLT = 30,
SLTU = 31,
XOR = 32,
SRL = 33,
SRA = 34,
OR = 35,
AND = 36,
FENCE = 37,
ECALL = 38,
EBREAK = 39,
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 tgc5c: public arch_if {
using virt_addr_t = typename traits<tgc5c>::virt_addr_t;
using phys_addr_t = typename traits<tgc5c>::phys_addr_t;
using reg_t = typename traits<tgc5c>::reg_t;
using addr_t = typename traits<tgc5c>::addr_t;
tgc5c();
~tgc5c();
void reset(uint64_t address=0) override;
uint8_t* get_regs_base_ptr() override;
inline uint64_t get_icount() { return reg.icount; }
inline bool should_stop() { return interrupt_sim; }
inline uint64_t stop_code() { return interrupt_sim; }
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; }
#pragma pack(push, 1)
struct TGC5C_regs {
uint32_t X0 = 0;
uint32_t X1 = 0;
uint32_t X2 = 0;
uint32_t X3 = 0;
uint32_t X4 = 0;
uint32_t X5 = 0;
uint32_t X6 = 0;
uint32_t X7 = 0;
uint32_t X8 = 0;
uint32_t X9 = 0;
uint32_t X10 = 0;
uint32_t X11 = 0;
uint32_t X12 = 0;
uint32_t X13 = 0;
uint32_t X14 = 0;
uint32_t X15 = 0;
uint32_t X16 = 0;
uint32_t X17 = 0;
uint32_t X18 = 0;
uint32_t X19 = 0;
uint32_t X20 = 0;
uint32_t X21 = 0;
uint32_t X22 = 0;
uint32_t X23 = 0;
uint32_t X24 = 0;
uint32_t X25 = 0;
uint32_t X26 = 0;
uint32_t X27 = 0;
uint32_t X28 = 0;
uint32_t X29 = 0;
uint32_t X30 = 0;
uint32_t X31 = 0;
uint32_t PC = 0;
uint32_t NEXT_PC = 0;
uint8_t PRIV = 0;
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 instruction = 0;
uint32_t last_branch = 0;
} reg;
#pragma pack(pop)
std::array<address_type, 4> addr_mode;
uint64_t interrupt_sim=0;
uint32_t get_fcsr(){return 0;}
void set_fcsr(uint32_t val){}
};
}
}
#endif /* _TGC5C_H_ */
// clang-format on

View File

@ -1,57 +0,0 @@
#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<iss::arch::tgc5c>;
#ifdef CORE_TGC5A
#include "riscv_hart_m_p.h"
#include <iss/arch/tgc5a.h>
using tgc5a_plat_type = iss::arch::riscv_hart_m_p<iss::arch::tgc5a>;
#endif
#ifdef CORE_TGC5B
#include "riscv_hart_m_p.h"
#include <iss/arch/tgc5b.h>
using tgc5b_plat_type = iss::arch::riscv_hart_m_p<iss::arch::tgc5b>;
#endif
#ifdef CORE_TGC5C_XRB_NN
#include "hwl.h"
#include "riscv_hart_m_p.h"
#include <iss/arch/tgc5c_xrb_nn.h>
using tgc5c_xrb_nn_plat_type = iss::arch::hwl<iss::arch::riscv_hart_m_p<iss::arch::tgc5c_xrb_nn>>;
#endif
#ifdef CORE_TGC5D
#include "riscv_hart_mu_p.h"
#include <iss/arch/tgc5d.h>
using tgc5d_plat_type = iss::arch::riscv_hart_mu_p<iss::arch::tgc5d, (iss::arch::features_e)(iss::arch::FEAT_PMP | iss::arch::FEAT_CLIC |
iss::arch::FEAT_EXT_N)>;
#endif
#ifdef CORE_TGC5D_XRB_MAC
#include "riscv_hart_mu_p.h"
#include <iss/arch/tgc5d_xrb_mac.h>
using tgc5d_xrb_mac_plat_type =
iss::arch::riscv_hart_mu_p<iss::arch::tgc5d_xrb_mac,
(iss::arch::features_e)(iss::arch::FEAT_PMP | iss::arch::FEAT_CLIC | iss::arch::FEAT_EXT_N)>;
#endif
#ifdef CORE_TGC5D_XRB_NN
#include "hwl.h"
#include "riscv_hart_mu_p.h"
#include <iss/arch/tgc5d_xrb_nn.h>
using tgc5d_xrb_nn_plat_type =
iss::arch::hwl<iss::arch::riscv_hart_mu_p<iss::arch::tgc5d_xrb_nn,
(iss::arch::features_e)(iss::arch::FEAT_PMP | iss::arch::FEAT_CLIC | iss::arch::FEAT_EXT_N)>>;
#endif
#ifdef CORE_TGC5E
#include "riscv_hart_mu_p.h"
#include <iss/arch/tgc5e.h>
using tgc5e_plat_type = iss::arch::riscv_hart_mu_p<iss::arch::tgc5e, (iss::arch::features_e)(iss::arch::FEAT_PMP | iss::arch::FEAT_CLIC |
iss::arch::FEAT_EXT_N)>;
#endif
#ifdef CORE_TGC5X
#include "riscv_hart_mu_p.h"
#include <iss/arch/tgc5x.h>
using tgc5x_plat_type = iss::arch::riscv_hart_mu_p<iss::arch::tgc5x, (iss::arch::features_e)(iss::arch::FEAT_PMP | iss::arch::FEAT_CLIC |
iss::arch::FEAT_EXT_N | iss::arch::FEAT_TCM)>;
#endif
#endif

View File

@ -1,171 +0,0 @@
/*******************************************************************************
* 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 <iss/vm_types.h>
#include <map>
#include <memory>
#include <util/ities.h>
#include <vector>
namespace iss {
namespace arch {
namespace cache {
enum class state { INVALID, VALID };
struct line {
uint64_t tag_addr{0};
state st{state::INVALID};
std::vector<uint8_t> data;
line(unsigned line_sz)
: data(line_sz) {}
};
struct set {
std::vector<line> ways;
set(unsigned ways_count, line const& l)
: ways(ways_count, l) {}
};
struct cache {
std::vector<set> 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 <typename BASE> class wt_cache : public BASE {
public:
using base_class = BASE;
using this_class = wt_cache<BASE>;
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<mem_read_f> cache_mem_rd_delegate;
std::function<mem_write_f> cache_mem_wr_delegate;
std::unique_ptr<cache::cache> dcache_ptr;
std::unique_ptr<cache::cache> icache_ptr;
size_t get_way_select() { return 0; }
};
template <typename BASE>
inline wt_cache<BASE>::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 <typename BASE> iss::status iss::arch::wt_cache<BASE>::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 <typename BASE> iss::status iss::arch::wt_cache<BASE>::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 */

View File

@ -1,106 +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.
*
*******************************************************************************/
#ifndef _ISS_FACTORY_H_
#define _ISS_FACTORY_H_
#include <algorithm>
#include <functional>
#include <iss/iss.h>
#include <memory>
#include <string>
#include <unordered_map>
#include <vector>
namespace iss {
using cpu_ptr = std::unique_ptr<iss::arch_if>;
using vm_ptr = std::unique_ptr<iss::vm_if>;
template <typename PLAT> std::tuple<cpu_ptr, vm_ptr> create_cpu(std::string const& backend, unsigned gdb_port) {
using core_type = typename PLAT::core;
core_type* lcpu = new PLAT();
if(backend == "interp")
return {cpu_ptr{lcpu}, vm_ptr{iss::interp::create(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")
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<iss::arch_if>;
using vm_ptr = std::unique_ptr<iss::vm_if>;
using base_t = std::tuple<cpu_ptr, vm_ptr>;
using create_fn = std::function<base_t(unsigned, void*)>;
using registry_t = std::unordered_map<std::string, create_fn>;
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<std::string> get_names() {
std::vector<std::string> keys{registry.size()};
std::transform(std::begin(registry), std::end(registry), std::begin(keys),
[](std::pair<std::string, create_fn> const& p) { return p.first; });
return keys;
}
};
} // namespace iss
#endif /* _ISS_FACTORY_H_ */

View File

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (C) 2017 - 2020 MINRES Technologies GmbH
* Copyright (C) 2017, 2018 MINRES Technologies GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -29,49 +29,51 @@
* POSSIBILITY OF SUCH DAMAGE.
*
*******************************************************************************/
<%
def getRegisterSizes(){
def regs = registers.collect{it.size}
regs[-1]=64 // correct for NEXT_PC
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 <util/logging.h>
#include <elfio/elfio.hpp>
#include <iss/arch/mnrv32.h>
#ifdef __cplusplus
extern "C" {
#endif
#include <ihex.h>
#ifdef __cplusplus
}
#endif
#include <cstdio>
#include <cstring>
#include <fstream>
using namespace iss::arch;
constexpr std::array<const char*, ${registers.size}> iss::arch::traits<iss::arch::${coreDef.name.toLowerCase()}>::reg_names;
constexpr std::array<const char*, ${registers.size}> iss::arch::traits<iss::arch::${coreDef.name.toLowerCase()}>::reg_aliases;
constexpr std::array<const uint32_t, ${getRegisterSizes().size}> iss::arch::traits<iss::arch::${coreDef.name.toLowerCase()}>::reg_bit_widths;
constexpr std::array<const uint32_t, ${getRegisterSizes().size}> iss::arch::traits<iss::arch::${coreDef.name.toLowerCase()}>::reg_byte_offsets;
constexpr std::array<const char*, 33> iss::arch::traits<iss::arch::mnrv32>::reg_names;
constexpr std::array<const char*, 33> iss::arch::traits<iss::arch::mnrv32>::reg_aliases;
constexpr std::array<const uint32_t, 39> iss::arch::traits<iss::arch::mnrv32>::reg_bit_widths;
constexpr std::array<const uint32_t, 40> iss::arch::traits<iss::arch::mnrv32>::reg_byte_offsets;
${coreDef.name.toLowerCase()}::${coreDef.name.toLowerCase()}() = default;
${coreDef.name.toLowerCase()}::~${coreDef.name.toLowerCase()}() = default;
void ${coreDef.name.toLowerCase()}::reset(uint64_t address) {
auto base_ptr = reinterpret_cast<traits<${coreDef.name.toLowerCase()}>::reg_t*>(get_regs_base_ptr());
for(size_t i=0; i<traits<${coreDef.name.toLowerCase()}>::NUM_REGS; ++i)
*(base_ptr+i)=0;
reg.PC=address;
reg.NEXT_PC=reg.PC;
reg.PRIV=0x3;
reg.trap_state=0;
mnrv32::mnrv32() {
reg.icount = 0;
}
uint8_t *${coreDef.name.toLowerCase()}::get_regs_base_ptr() {
mnrv32::~mnrv32() = default;
void mnrv32::reset(uint64_t address) {
for(size_t i=0; i<traits<mnrv32>::NUM_REGS; ++i) set_reg(i, std::vector<uint8_t>(sizeof(traits<mnrv32>::reg_t),0));
reg.PC=address;
reg.NEXT_PC=reg.PC;
reg.trap_state=0;
reg.machine_state=0x3;
reg.icount=0;
}
uint8_t *mnrv32::get_regs_base_ptr() {
return reinterpret_cast<uint8_t*>(&reg);
}
${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);
mnrv32::phys_addr_t mnrv32::virt2phys(const iss::addr_t &pc) {
return phys_addr_t(pc); // change logical address to physical address
}
// clang-format on

View File

@ -1,8 +0,0 @@
# 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).

View File

@ -1,114 +0,0 @@
/*******************************************************************************
* 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 <iss/plugin/calculator.h>
#include <yaml-cpp/yaml.h>
#include <fstream>
#include <iss/arch_if.h>
#include <util/logging.h>
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<uint32_t*>(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) {
CPPLOG(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<unsigned>();
if(delays.size() <= idx)
delays.resize(idx + 1);
auto& res = delays[idx];
res.is_branch = instr.second["branch"].as<bool>();
auto delay = instr.second["delay"];
if(delay.IsSequence()) {
res.not_taken = delay[0].as<uint64_t>();
res.taken = delay[1].as<uint64_t>();
} else {
try {
res.not_taken = delay.as<uint64_t>();
res.taken = res.not_taken;
} catch(const YAML::BadConversion& e) {
res.f = iss::plugin::calculator(reg_base_ptr, delay.as<std::string>());
}
}
}
}
} catch(YAML::ParserException& e) {
CPPLOG(ERR) << "Could not parse input file " << config_file_name << ", reason: " << e.what();
return false;
}
} else {
CPPLOG(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;
}
}

80
src/iss/rv32gc.cpp Normal file
View File

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

77
src/iss/rv32imac.cpp Normal file
View File

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

View File

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (C) 2021 MINRES Technologies GmbH
* Copyright (C) 2017, 2018 MINRES Technologies GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -30,61 +30,52 @@
*
*******************************************************************************/
#ifndef _ISS_FACTORY_H_
#define _ISS_FACTORY_H_
#include "sc_core_adapter_if.h"
#include <algorithm>
#include <functional>
#include <iss/iss.h>
#include <memory>
#include <string>
#include <unordered_map>
#include <vector>
namespace sysc {
#include "util/ities.h"
#include <util/logging.h>
using sc_cpu_ptr = std::unique_ptr<sc_core_adapter_if>;
using vm_ptr = std::unique_ptr<iss::vm_if>;
#include <elfio/elfio.hpp>
#include <iss/arch/rv64gc.h>
class iss_factory {
public:
using base_t = std::tuple<sc_cpu_ptr, vm_ptr>;
using create_fn = std::function<base_t(unsigned, void*)>;
using registry_t = std::unordered_map<std::string, create_fn>;
#ifdef __cplusplus
extern "C" {
#endif
#include <ihex.h>
#ifdef __cplusplus
}
#endif
#include <cstdio>
#include <cstring>
#include <fstream>
iss_factory() = default;
iss_factory(const iss_factory&) = delete;
iss_factory& operator=(const iss_factory&) = delete;
using namespace iss::arch;
static iss_factory& instance() {
static iss_factory bf;
return bf;
constexpr std::array<const char*, 66> iss::arch::traits<iss::arch::rv64gc>::reg_names;
constexpr std::array<const char*, 66> iss::arch::traits<iss::arch::rv64gc>::reg_aliases;
constexpr std::array<const uint32_t, 72> iss::arch::traits<iss::arch::rv64gc>::reg_bit_widths;
constexpr std::array<const uint32_t, 73> iss::arch::traits<iss::arch::rv64gc>::reg_byte_offsets;
rv64gc::rv64gc() {
reg.icount = 0;
}
bool register_creator(const std::string& className, create_fn const& fn) {
registry[className] = fn;
return true;
rv64gc::~rv64gc() = default;
void rv64gc::reset(uint64_t address) {
for(size_t i=0; i<traits<rv64gc>::NUM_REGS; ++i) set_reg(i, std::vector<uint8_t>(sizeof(traits<rv64gc>::reg_t),0));
reg.PC=address;
reg.NEXT_PC=reg.PC;
reg.trap_state=0;
reg.machine_state=0x3;
reg.icount=0;
}
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};
uint8_t *rv64gc::get_regs_base_ptr() {
return reinterpret_cast<uint8_t*>(&reg);
}
std::vector<std::string> get_names() {
std::vector<std::string> keys{registry.size()};
std::transform(std::begin(registry), std::end(registry), std::begin(keys),
[](std::pair<std::string, create_fn> const& p) { return p.first; });
return keys;
rv64gc::phys_addr_t rv64gc::virt2phys(const iss::addr_t &pc) {
return phys_addr_t(pc); // change logical address to physical address
}
private:
registry_t registry;
};
} // namespace sysc
#endif /* _ISS_FACTORY_H_ */

Some files were not shown because too many files have changed in this diff Show More