Merge branch 'develop' into main
This commit is contained in:
commit
926a03c346
|
@ -1,4 +1,3 @@
|
|||
---
|
||||
Language: Cpp
|
||||
# BasedOnStyle: LLVM
|
||||
# should be in line with IndentWidth
|
||||
|
@ -13,8 +12,8 @@ AllowAllParametersOfDeclarationOnNextLine: true
|
|||
AllowShortBlocksOnASingleLine: false
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: All
|
||||
AllowShortIfStatementsOnASingleLine: true
|
||||
AllowShortLoopsOnASingleLine: true
|
||||
AllowShortIfStatementsOnASingleLine: false
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AlwaysBreakAfterDefinitionReturnType: None
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: false
|
||||
|
@ -39,8 +38,8 @@ BreakBeforeTernaryOperators: true
|
|||
BreakConstructorInitializersBeforeComma: true
|
||||
BreakAfterJavaFieldAnnotations: false
|
||||
BreakStringLiterals: true
|
||||
ColumnLimit: 120
|
||||
CommentPragmas: '^ IWYU pragma:'
|
||||
ColumnLimit: 140
|
||||
CommentPragmas: '^( IWYU pragma:| @suppress)'
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
||||
ConstructorInitializerIndentWidth: 0
|
||||
ContinuationIndentWidth: 4
|
||||
|
@ -76,13 +75,13 @@ PenaltyBreakFirstLessLess: 120
|
|||
PenaltyBreakString: 1000
|
||||
PenaltyExcessCharacter: 1000000
|
||||
PenaltyReturnTypeOnItsOwnLine: 60
|
||||
PointerAlignment: Right
|
||||
PointerAlignment: Left
|
||||
ReflowComments: true
|
||||
SortIncludes: true
|
||||
SpaceAfterCStyleCast: false
|
||||
SpaceAfterTemplateKeyword: true
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeParens: ControlStatements
|
||||
SpaceBeforeParens: Never
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesBeforeTrailingComments: 1
|
||||
SpacesInAngles: false
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
.DS_Store
|
||||
/*.il
|
||||
/.settings
|
||||
/avr-instr.html
|
||||
/blink.S
|
||||
/flash.*
|
||||
|
@ -14,7 +15,6 @@
|
|||
/*.ods
|
||||
/build*/
|
||||
/*.logs
|
||||
language.settings.xml
|
||||
/*.gtkw
|
||||
/Debug wo LLVM/
|
||||
/*.txdb
|
||||
|
@ -30,6 +30,5 @@ language.settings.xml
|
|||
/.gdbinit
|
||||
/*.out
|
||||
/dump.json
|
||||
/src-gen/
|
||||
/*.yaml
|
||||
/*.json
|
||||
|
|
1
.project
1
.project
|
@ -23,6 +23,5 @@
|
|||
<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>
|
||||
|
|
|
@ -1,73 +0,0 @@
|
|||
eclipse.preferences.version=1
|
||||
org.eclipse.cdt.codan.checkers.errnoreturn=Warning
|
||||
org.eclipse.cdt.codan.checkers.errnoreturn.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"No return\\")",implicit\=>false}
|
||||
org.eclipse.cdt.codan.checkers.errreturnvalue=Error
|
||||
org.eclipse.cdt.codan.checkers.errreturnvalue.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Unused return value\\")"}
|
||||
org.eclipse.cdt.codan.checkers.nocommentinside=-Error
|
||||
org.eclipse.cdt.codan.checkers.nocommentinside.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Nesting comments\\")"}
|
||||
org.eclipse.cdt.codan.checkers.nolinecomment=-Error
|
||||
org.eclipse.cdt.codan.checkers.nolinecomment.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Line comments\\")"}
|
||||
org.eclipse.cdt.codan.checkers.noreturn=Error
|
||||
org.eclipse.cdt.codan.checkers.noreturn.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"No return value\\")",implicit\=>false}
|
||||
org.eclipse.cdt.codan.internal.checkers.AbstractClassCreation=Error
|
||||
org.eclipse.cdt.codan.internal.checkers.AbstractClassCreation.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Abstract class cannot be instantiated\\")"}
|
||||
org.eclipse.cdt.codan.internal.checkers.AmbiguousProblem=Error
|
||||
org.eclipse.cdt.codan.internal.checkers.AmbiguousProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Ambiguous problem\\")"}
|
||||
org.eclipse.cdt.codan.internal.checkers.AssignmentInConditionProblem=Warning
|
||||
org.eclipse.cdt.codan.internal.checkers.AssignmentInConditionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Assignment in condition\\")"}
|
||||
org.eclipse.cdt.codan.internal.checkers.AssignmentToItselfProblem=Error
|
||||
org.eclipse.cdt.codan.internal.checkers.AssignmentToItselfProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Assignment to itself\\")"}
|
||||
org.eclipse.cdt.codan.internal.checkers.CaseBreakProblem=Warning
|
||||
org.eclipse.cdt.codan.internal.checkers.CaseBreakProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"No break at end of case\\")",no_break_comment\=>"no break",last_case_param\=>false,empty_case_param\=>false,enable_fallthrough_quickfix_param\=>false}
|
||||
org.eclipse.cdt.codan.internal.checkers.CatchByReference=Warning
|
||||
org.eclipse.cdt.codan.internal.checkers.CatchByReference.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Catching by reference is recommended\\")",unknown\=>false,exceptions\=>()}
|
||||
org.eclipse.cdt.codan.internal.checkers.CircularReferenceProblem=Error
|
||||
org.eclipse.cdt.codan.internal.checkers.CircularReferenceProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Circular inheritance\\")"}
|
||||
org.eclipse.cdt.codan.internal.checkers.ClassMembersInitialization=Warning
|
||||
org.eclipse.cdt.codan.internal.checkers.ClassMembersInitialization.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Class members should be properly initialized\\")",skip\=>true}
|
||||
org.eclipse.cdt.codan.internal.checkers.DecltypeAutoProblem=Error
|
||||
org.eclipse.cdt.codan.internal.checkers.DecltypeAutoProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid 'decltype(auto)' specifier\\")"}
|
||||
org.eclipse.cdt.codan.internal.checkers.FieldResolutionProblem=Error
|
||||
org.eclipse.cdt.codan.internal.checkers.FieldResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Field cannot be resolved\\")"}
|
||||
org.eclipse.cdt.codan.internal.checkers.FunctionResolutionProblem=Error
|
||||
org.eclipse.cdt.codan.internal.checkers.FunctionResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Function cannot be resolved\\")"}
|
||||
org.eclipse.cdt.codan.internal.checkers.InvalidArguments=Error
|
||||
org.eclipse.cdt.codan.internal.checkers.InvalidArguments.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid arguments\\")"}
|
||||
org.eclipse.cdt.codan.internal.checkers.InvalidTemplateArgumentsProblem=Error
|
||||
org.eclipse.cdt.codan.internal.checkers.InvalidTemplateArgumentsProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid template argument\\")"}
|
||||
org.eclipse.cdt.codan.internal.checkers.LabelStatementNotFoundProblem=Error
|
||||
org.eclipse.cdt.codan.internal.checkers.LabelStatementNotFoundProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Label statement not found\\")"}
|
||||
org.eclipse.cdt.codan.internal.checkers.MemberDeclarationNotFoundProblem=Error
|
||||
org.eclipse.cdt.codan.internal.checkers.MemberDeclarationNotFoundProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Member declaration not found\\")"}
|
||||
org.eclipse.cdt.codan.internal.checkers.MethodResolutionProblem=Error
|
||||
org.eclipse.cdt.codan.internal.checkers.MethodResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Method cannot be resolved\\")"}
|
||||
org.eclipse.cdt.codan.internal.checkers.NamingConventionFunctionChecker=-Info
|
||||
org.eclipse.cdt.codan.internal.checkers.NamingConventionFunctionChecker.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Name convention for function\\")",pattern\=>"^[a-z]",macro\=>true,exceptions\=>()}
|
||||
org.eclipse.cdt.codan.internal.checkers.NonVirtualDestructorProblem=Warning
|
||||
org.eclipse.cdt.codan.internal.checkers.NonVirtualDestructorProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Class has a virtual method and non-virtual destructor\\")"}
|
||||
org.eclipse.cdt.codan.internal.checkers.OverloadProblem=Error
|
||||
org.eclipse.cdt.codan.internal.checkers.OverloadProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid overload\\")"}
|
||||
org.eclipse.cdt.codan.internal.checkers.RedeclarationProblem=Error
|
||||
org.eclipse.cdt.codan.internal.checkers.RedeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid redeclaration\\")"}
|
||||
org.eclipse.cdt.codan.internal.checkers.RedefinitionProblem=Error
|
||||
org.eclipse.cdt.codan.internal.checkers.RedefinitionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid redefinition\\")"}
|
||||
org.eclipse.cdt.codan.internal.checkers.ReturnStyleProblem=-Warning
|
||||
org.eclipse.cdt.codan.internal.checkers.ReturnStyleProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Return with parenthesis\\")"}
|
||||
org.eclipse.cdt.codan.internal.checkers.ScanfFormatStringSecurityProblem=-Warning
|
||||
org.eclipse.cdt.codan.internal.checkers.ScanfFormatStringSecurityProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Format String Vulnerability\\")"}
|
||||
org.eclipse.cdt.codan.internal.checkers.StatementHasNoEffectProblem=Warning
|
||||
org.eclipse.cdt.codan.internal.checkers.StatementHasNoEffectProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Statement has no effect\\")",macro\=>true,exceptions\=>()}
|
||||
org.eclipse.cdt.codan.internal.checkers.SuggestedParenthesisProblem=Warning
|
||||
org.eclipse.cdt.codan.internal.checkers.SuggestedParenthesisProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Suggested parenthesis around expression\\")",paramNot\=>false}
|
||||
org.eclipse.cdt.codan.internal.checkers.SuspiciousSemicolonProblem=Warning
|
||||
org.eclipse.cdt.codan.internal.checkers.SuspiciousSemicolonProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Suspicious semicolon\\")",else\=>false,afterelse\=>false}
|
||||
org.eclipse.cdt.codan.internal.checkers.TypeResolutionProblem=Error
|
||||
org.eclipse.cdt.codan.internal.checkers.TypeResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Type cannot be resolved\\")"}
|
||||
org.eclipse.cdt.codan.internal.checkers.UnusedFunctionDeclarationProblem=Warning
|
||||
org.eclipse.cdt.codan.internal.checkers.UnusedFunctionDeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Unused function declaration\\")",macro\=>true}
|
||||
org.eclipse.cdt.codan.internal.checkers.UnusedStaticFunctionProblem=Warning
|
||||
org.eclipse.cdt.codan.internal.checkers.UnusedStaticFunctionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Unused static function\\")",macro\=>true}
|
||||
org.eclipse.cdt.codan.internal.checkers.UnusedVariableDeclarationProblem=Warning
|
||||
org.eclipse.cdt.codan.internal.checkers.UnusedVariableDeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Unused variable declaration in file scope\\")",macro\=>true,exceptions\=>("@(\#)","$Id")}
|
||||
org.eclipse.cdt.codan.internal.checkers.VariableResolutionProblem=Error
|
||||
org.eclipse.cdt.codan.internal.checkers.VariableResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Symbol is not resolved\\")"}
|
|
@ -1,13 +0,0 @@
|
|||
eclipse.preferences.version=1
|
||||
environment/project/cdt.managedbuild.config.gnu.exe.debug.1751741082/append=true
|
||||
environment/project/cdt.managedbuild.config.gnu.exe.debug.1751741082/appendContributed=true
|
||||
environment/project/cdt.managedbuild.config.gnu.exe.release.1745230171.1259602404/LLVM_HOME/delimiter=\:
|
||||
environment/project/cdt.managedbuild.config.gnu.exe.release.1745230171.1259602404/LLVM_HOME/operation=append
|
||||
environment/project/cdt.managedbuild.config.gnu.exe.release.1745230171.1259602404/LLVM_HOME/value=/usr/lib/llvm-6.0
|
||||
environment/project/cdt.managedbuild.config.gnu.exe.release.1745230171.1259602404/append=true
|
||||
environment/project/cdt.managedbuild.config.gnu.exe.release.1745230171.1259602404/appendContributed=true
|
||||
environment/project/cdt.managedbuild.config.gnu.exe.release.1745230171/LLVM_HOME/delimiter=\:
|
||||
environment/project/cdt.managedbuild.config.gnu.exe.release.1745230171/LLVM_HOME/operation=append
|
||||
environment/project/cdt.managedbuild.config.gnu.exe.release.1745230171/LLVM_HOME/value=/usr/lib/llvm-6.0
|
||||
environment/project/cdt.managedbuild.config.gnu.exe.release.1745230171/append=true
|
||||
environment/project/cdt.managedbuild.config.gnu.exe.release.1745230171/appendContributed=true
|
|
@ -1,37 +0,0 @@
|
|||
eclipse.preferences.version=1
|
||||
environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.debug.1751741082/CPATH/delimiter=\:
|
||||
environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.debug.1751741082/CPATH/operation=remove
|
||||
environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.debug.1751741082/CPLUS_INCLUDE_PATH/delimiter=\:
|
||||
environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.debug.1751741082/CPLUS_INCLUDE_PATH/operation=remove
|
||||
environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.debug.1751741082/C_INCLUDE_PATH/delimiter=\:
|
||||
environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.debug.1751741082/C_INCLUDE_PATH/operation=remove
|
||||
environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.debug.1751741082/append=true
|
||||
environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.debug.1751741082/appendContributed=true
|
||||
environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.release.1745230171.1259602404/CPATH/delimiter=\:
|
||||
environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.release.1745230171.1259602404/CPATH/operation=remove
|
||||
environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.release.1745230171.1259602404/CPLUS_INCLUDE_PATH/delimiter=\:
|
||||
environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.release.1745230171.1259602404/CPLUS_INCLUDE_PATH/operation=remove
|
||||
environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.release.1745230171.1259602404/C_INCLUDE_PATH/delimiter=\:
|
||||
environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.release.1745230171.1259602404/C_INCLUDE_PATH/operation=remove
|
||||
environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.release.1745230171.1259602404/append=true
|
||||
environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.release.1745230171.1259602404/appendContributed=true
|
||||
environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.release.1745230171/CPATH/delimiter=\:
|
||||
environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.release.1745230171/CPATH/operation=remove
|
||||
environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.release.1745230171/CPLUS_INCLUDE_PATH/delimiter=\:
|
||||
environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.release.1745230171/CPLUS_INCLUDE_PATH/operation=remove
|
||||
environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.release.1745230171/C_INCLUDE_PATH/delimiter=\:
|
||||
environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.release.1745230171/C_INCLUDE_PATH/operation=remove
|
||||
environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.release.1745230171/append=true
|
||||
environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.release.1745230171/appendContributed=true
|
||||
environment/buildEnvironmentLibrary/cdt.managedbuild.config.gnu.exe.debug.1751741082/LIBRARY_PATH/delimiter=\:
|
||||
environment/buildEnvironmentLibrary/cdt.managedbuild.config.gnu.exe.debug.1751741082/LIBRARY_PATH/operation=remove
|
||||
environment/buildEnvironmentLibrary/cdt.managedbuild.config.gnu.exe.debug.1751741082/append=true
|
||||
environment/buildEnvironmentLibrary/cdt.managedbuild.config.gnu.exe.debug.1751741082/appendContributed=true
|
||||
environment/buildEnvironmentLibrary/cdt.managedbuild.config.gnu.exe.release.1745230171.1259602404/LIBRARY_PATH/delimiter=\:
|
||||
environment/buildEnvironmentLibrary/cdt.managedbuild.config.gnu.exe.release.1745230171.1259602404/LIBRARY_PATH/operation=remove
|
||||
environment/buildEnvironmentLibrary/cdt.managedbuild.config.gnu.exe.release.1745230171.1259602404/append=true
|
||||
environment/buildEnvironmentLibrary/cdt.managedbuild.config.gnu.exe.release.1745230171.1259602404/appendContributed=true
|
||||
environment/buildEnvironmentLibrary/cdt.managedbuild.config.gnu.exe.release.1745230171/LIBRARY_PATH/delimiter=\:
|
||||
environment/buildEnvironmentLibrary/cdt.managedbuild.config.gnu.exe.release.1745230171/LIBRARY_PATH/operation=remove
|
||||
environment/buildEnvironmentLibrary/cdt.managedbuild.config.gnu.exe.release.1745230171/append=true
|
||||
environment/buildEnvironmentLibrary/cdt.managedbuild.config.gnu.exe.release.1745230171/appendContributed=true
|
200
CMakeLists.txt
200
CMakeLists.txt
|
@ -1,92 +1,106 @@
|
|||
cmake_minimum_required(VERSION 3.12)
|
||||
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
|
||||
###############################################################################
|
||||
#
|
||||
###############################################################################
|
||||
project(dbt-rise-tgc VERSION 1.0.0)
|
||||
|
||||
include(GNUInstallDirs)
|
||||
include(flink)
|
||||
|
||||
find_package(elfio QUIET)
|
||||
find_package(Boost COMPONENTS coroutine)
|
||||
|
||||
if(WITH_LLVM)
|
||||
if(DEFINED ENV{LLVM_HOME})
|
||||
find_path (LLVM_DIR LLVM-Config.cmake $ENV{LLVM_HOME}/lib/cmake/llvm)
|
||||
endif(DEFINED ENV{LLVM_HOME})
|
||||
find_package(LLVM REQUIRED CONFIG)
|
||||
message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}")
|
||||
message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}")
|
||||
llvm_map_components_to_libnames(llvm_libs support core mcjit x86codegen x86asmparser)
|
||||
endif()
|
||||
|
||||
#Mac needed variables (adapt for your needs - http://www.cmake.org/Wiki/CMake_RPATH_handling#Mac_OS_X_and_the_RPATH)
|
||||
#set(CMAKE_MACOSX_RPATH ON)
|
||||
#set(CMAKE_SKIP_BUILD_RPATH FALSE)
|
||||
#set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE)
|
||||
#set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")
|
||||
#set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
|
||||
find_package(jsoncpp)
|
||||
find_package(Boost COMPONENTS coroutine REQUIRED)
|
||||
|
||||
add_subdirectory(softfloat)
|
||||
|
||||
# library files
|
||||
FILE(GLOB TGC_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/iss/*.cpp)
|
||||
FILE(GLOB TGC_VM_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/vm/interp/vm_*.cpp)
|
||||
|
||||
set(LIB_SOURCES
|
||||
src/iss/plugin/instruction_count.cpp
|
||||
src/iss/arch/tgc5c.cpp
|
||||
src/vm/interp/vm_tgc5c.cpp
|
||||
src/vm/fp_functions.cpp
|
||||
src/plugin/instruction_count.cpp
|
||||
|
||||
${TGC_SOURCES}
|
||||
${TGC_VM_SOURCES}
|
||||
)
|
||||
if(TARGET RapidJSON)
|
||||
list(APPEND LIB_SOURCES src/plugin/cycle_estimate.cpp src/plugin/pctrace.cpp)
|
||||
if(WITH_TCC)
|
||||
list(APPEND LIB_SOURCES
|
||||
src/vm/tcc/vm_tgc5c.cpp
|
||||
)
|
||||
endif()
|
||||
if(WITH_LLVM)
|
||||
list(APPEND LIB_SOURCES
|
||||
src/vm/llvm/vm_tgc5c.cpp
|
||||
src/vm/llvm/fp_impl.cpp
|
||||
)
|
||||
endif()
|
||||
if(WITH_ASMJIT)
|
||||
list(APPEND LIB_SOURCES
|
||||
src/vm/asmjit/vm_tgc5c.cpp
|
||||
)
|
||||
endif()
|
||||
# library files
|
||||
FILE(GLOB GEN_ISS_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src-gen/iss/arch/*.cpp)
|
||||
FILE(GLOB GEN_VM_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src-gen/vm/interp/vm_*.cpp)
|
||||
FILE(GLOB GEN_YAML_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/contrib/instr/*.yaml)
|
||||
list(APPEND LIB_SOURCES ${GEN_ISS_SOURCES} ${GEN_VM_SOURCES})
|
||||
foreach(FILEPATH ${GEN_ISS_SOURCES})
|
||||
get_filename_component(CORE ${FILEPATH} NAME_WE)
|
||||
string(TOUPPER ${CORE} CORE)
|
||||
list(APPEND LIB_DEFINES CORE_${CORE})
|
||||
endforeach()
|
||||
message(STATUS "Core defines are ${LIB_DEFINES}")
|
||||
|
||||
if(WITH_LLVM)
|
||||
FILE(GLOB TGC_LLVM_SOURCES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/vm/llvm/vm_*.cpp
|
||||
)
|
||||
list(APPEND LIB_SOURCES ${TGC_LLVM_SOURCES})
|
||||
FILE(GLOB LLVM_GEN_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src-gen/vm/llvm/vm_*.cpp)
|
||||
list(APPEND LIB_SOURCES ${LLVM_GEN_SOURCES})
|
||||
endif()
|
||||
|
||||
if(WITH_TCC)
|
||||
FILE(GLOB TGC_TCC_SOURCES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/vm/tcc/vm_*.cpp
|
||||
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
|
||||
)
|
||||
list(APPEND LIB_SOURCES ${TGC_TCC_SOURCES})
|
||||
endif()
|
||||
|
||||
# Define the library
|
||||
add_library(${PROJECT_NAME} ${LIB_SOURCES})
|
||||
# list code gen dependencies
|
||||
if(TARGET ${CORE_NAME}_cpp)
|
||||
add_dependencies(${PROJECT_NAME} ${CORE_NAME}_cpp)
|
||||
endif()
|
||||
add_library(${PROJECT_NAME} SHARED ${LIB_SOURCES})
|
||||
|
||||
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
|
||||
target_compile_options(${PROJECT_NAME} PRIVATE -Wno-shift-count-overflow)
|
||||
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
||||
target_compile_options(${PROJECT_NAME} PRIVATE /wd4293)
|
||||
endif()
|
||||
target_include_directories(${PROJECT_NAME} PUBLIC incl)
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC softfloat scc-util jsoncpp Boost::coroutine)
|
||||
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC -Wl,--whole-archive dbt-rise-core -Wl,--no-whole-archive)
|
||||
else()
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC dbt-rise-core)
|
||||
endif()
|
||||
if(TARGET CONAN_PKG::elfio)
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC CONAN_PKG::elfio)
|
||||
elseif(TARGET elfio::elfio)
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC elfio::elfio)
|
||||
else()
|
||||
message(FATAL_ERROR "No elfio library found, maybe a find_package() call is missing")
|
||||
endif()
|
||||
if(TARGET RapidJSON)
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC RapidJSON)
|
||||
target_include_directories(${PROJECT_NAME} PUBLIC src)
|
||||
target_include_directories(${PROJECT_NAME} PUBLIC src-gen)
|
||||
|
||||
target_force_link_libraries(${PROJECT_NAME} PRIVATE dbt-rise-core)
|
||||
# only re-export the include paths
|
||||
get_target_property(DBT_CORE_INCL dbt-rise-core INTERFACE_INCLUDE_DIRECTORIES)
|
||||
target_include_directories(${PROJECT_NAME} INTERFACE ${DBT_CORE_INCL})
|
||||
get_target_property(DBT_CORE_DEFS dbt-rise-core INTERFACE_COMPILE_DEFINITIONS)
|
||||
if(NOT (DBT_CORE_DEFS STREQUAL DBT_CORE_DEFS-NOTFOUND))
|
||||
target_compile_definitions(${PROJECT_NAME} INTERFACE ${DBT_CORE_DEFS})
|
||||
endif()
|
||||
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC elfio::elfio softfloat scc-util Boost::coroutine)
|
||||
if(TARGET yaml-cpp::yaml-cpp)
|
||||
target_compile_definitions(${PROJECT_NAME} PUBLIC WITH_PLUGINS)
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC yaml-cpp::yaml-cpp)
|
||||
endif()
|
||||
|
||||
if(WITH_LLVM)
|
||||
find_package(LLVM)
|
||||
target_compile_definitions(${PROJECT_NAME} PUBLIC ${LLVM_DEFINITIONS})
|
||||
target_include_directories(${PROJECT_NAME} PUBLIC ${LLVM_INCLUDE_DIRS})
|
||||
if(BUILD_SHARED_LIBS)
|
||||
target_link_libraries( ${PROJECT_NAME} PUBLIC ${LLVM_LIBRARIES})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set_target_properties(${PROJECT_NAME} PROPERTIES
|
||||
VERSION ${PROJECT_VERSION}
|
||||
|
@ -106,25 +120,43 @@ install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/incl/iss COMPONENT ${PROJECT_NAME}
|
|||
FILES_MATCHING # install only matched files
|
||||
PATTERN "*.h" # select header files
|
||||
)
|
||||
install(FILES ${GEN_YAML_SOURCES} DESTINATION share/tgc-vp)
|
||||
###############################################################################
|
||||
#
|
||||
###############################################################################
|
||||
set(CMAKE_INSTALL_RPATH $ORIGIN/../${CMAKE_INSTALL_LIBDIR})
|
||||
project(tgc-sim)
|
||||
find_package(Boost COMPONENTS program_options thread REQUIRED)
|
||||
|
||||
add_executable(${PROJECT_NAME} src/main.cpp)
|
||||
if(TARGET ${CORE_NAME}_cpp)
|
||||
list(APPEND TGC_SOURCES ${${CORE_NAME}_OUTPUT_FILES})
|
||||
else()
|
||||
FILE(GLOB TGC_SOURCES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src-gen/iss/arch/*.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src-gen/vm/interp/vm_*.cpp
|
||||
)
|
||||
list(APPEND TGC_SOURCES ${GEN_SOURCES})
|
||||
endif()
|
||||
|
||||
foreach(F IN LISTS TGC_SOURCES)
|
||||
if (${F} MATCHES ".*/arch/([^/]*)\.cpp")
|
||||
string(REGEX REPLACE ".*/([^/]*)\.cpp" "\\1" CORE_NAME_LC ${F})
|
||||
string(TOUPPER ${CORE_NAME_LC} CORE_NAME)
|
||||
target_compile_definitions(${PROJECT_NAME} PRIVATE CORE_${CORE_NAME})
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
if(WITH_LLVM)
|
||||
target_compile_definitions(${PROJECT_NAME} PRIVATE WITH_LLVM)
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC ${llvm_libs})
|
||||
endif()
|
||||
# Links the target exe against the libraries
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC dbt-rise-tgc)
|
||||
#if(WITH_LLVM)
|
||||
# target_compile_definitions(${PROJECT_NAME} PRIVATE WITH_LLVM)
|
||||
# #target_link_libraries(${PROJECT_NAME} PUBLIC ${llvm_libs})
|
||||
#endif()
|
||||
#if(WITH_TCC)
|
||||
# target_compile_definitions(${PROJECT_NAME} PRIVATE WITH_TCC)
|
||||
#endif()
|
||||
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC dbt-rise-tgc fmt::fmt)
|
||||
|
||||
if(TARGET Boost::program_options)
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC Boost::program_options)
|
||||
else()
|
||||
|
@ -144,27 +176,51 @@ install(TARGETS tgc-sim
|
|||
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME} # headers for mac (note the different component -> different package)
|
||||
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} # headers
|
||||
)
|
||||
|
||||
if(BUILD_TESTING)
|
||||
# ... CMake code to create tests ...
|
||||
add_test(NAME tgc-sim-interp
|
||||
COMMAND tgc-sim -f ${CMAKE_BINARY_DIR}/../../Firmwares/hello-world/hello --backend interp)
|
||||
if(WITH_TCC)
|
||||
add_test(NAME tgc-sim-tcc
|
||||
COMMAND tgc-sim -f ${CMAKE_BINARY_DIR}/../../Firmwares/hello-world/hello --backend tcc)
|
||||
endif()
|
||||
if(WITH_LLVM)
|
||||
add_test(NAME tgc-sim-llvm
|
||||
COMMAND tgc-sim -f ${CMAKE_BINARY_DIR}/../../Firmwares/hello-world/hello --backend llvm)
|
||||
endif()
|
||||
if(WITH_ASMJIT)
|
||||
add_test(NAME tgc-sim-asmjit
|
||||
COMMAND tgc-sim -f ${CMAKE_BINARY_DIR}/../../Firmwares/hello-world/hello --backend asmjit)
|
||||
endif()
|
||||
endif()
|
||||
###############################################################################
|
||||
#
|
||||
###############################################################################
|
||||
if(TARGET scc-sysc)
|
||||
project(dbt-rise-tgc_sc VERSION 1.0.0)
|
||||
|
||||
include(SystemCPackage)
|
||||
if(SystemC_FOUND)
|
||||
add_library(${PROJECT_NAME} src/sysc/core_complex.cpp)
|
||||
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})
|
||||
endforeach()
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC dbt-rise-tgc scc)
|
||||
if(WITH_LLVM)
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC ${llvm_libs})
|
||||
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}/incl/sysc/core_complex.h)
|
||||
set(LIB_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/src/sysc/core_complex.h)
|
||||
set_target_properties(${PROJECT_NAME} PROPERTIES
|
||||
VERSION ${PROJECT_VERSION}
|
||||
FRAMEWORK FALSE
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
# according to https://github.com/horance-liu/flink.cmake/tree/master
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
include(CMakeParseArguments)
|
||||
|
||||
function(target_do_force_link_libraries target visibility lib)
|
||||
if(MSVC)
|
||||
target_link_libraries(${target} ${visibility} "/WHOLEARCHIVE:${lib}")
|
||||
elseif(APPLE)
|
||||
target_link_libraries(${target} ${visibility} -Wl,-force_load ${lib})
|
||||
else()
|
||||
target_link_libraries(${target} ${visibility} -Wl,--whole-archive ${lib} -Wl,--no-whole-archive)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(target_force_link_libraries target)
|
||||
cmake_parse_arguments(FLINK
|
||||
""
|
||||
""
|
||||
"PUBLIC;INTERFACE;PRIVATE"
|
||||
${ARGN}
|
||||
)
|
||||
|
||||
foreach(lib IN LISTS FLINK_PUBLIC)
|
||||
target_do_force_link_libraries(${target} PUBLIC ${lib})
|
||||
endforeach()
|
||||
|
||||
foreach(lib IN LISTS FLINK_INTERFACE)
|
||||
target_do_force_link_libraries(${target} INTERFACE ${lib})
|
||||
endforeach()
|
||||
|
||||
foreach(lib IN LISTS FLINK_PRIVATE)
|
||||
target_do_force_link_libraries(${target} PRIVATE ${lib})
|
||||
endforeach()
|
||||
endfunction()
|
|
@ -0,0 +1 @@
|
|||
/*.yaml
|
|
@ -0,0 +1,624 @@
|
|||
|
||||
RVI:
|
||||
LUI:
|
||||
index: 0
|
||||
encoding: 0b00000000000000000000000000110111
|
||||
mask: 0b00000000000000000000000001111111
|
||||
size: 32
|
||||
branch: false
|
||||
delay: 1
|
||||
AUIPC:
|
||||
index: 1
|
||||
encoding: 0b00000000000000000000000000010111
|
||||
mask: 0b00000000000000000000000001111111
|
||||
size: 32
|
||||
branch: false
|
||||
delay: 1
|
||||
JAL:
|
||||
index: 2
|
||||
encoding: 0b00000000000000000000000001101111
|
||||
mask: 0b00000000000000000000000001111111
|
||||
size: 32
|
||||
branch: true
|
||||
delay: 1
|
||||
JALR:
|
||||
index: 3
|
||||
encoding: 0b00000000000000000000000001100111
|
||||
mask: 0b00000000000000000111000001111111
|
||||
size: 32
|
||||
branch: true
|
||||
delay: [1,1]
|
||||
BEQ:
|
||||
index: 4
|
||||
encoding: 0b00000000000000000000000001100011
|
||||
mask: 0b00000000000000000111000001111111
|
||||
size: 32
|
||||
branch: true
|
||||
delay: [1,1]
|
||||
BNE:
|
||||
index: 5
|
||||
encoding: 0b00000000000000000001000001100011
|
||||
mask: 0b00000000000000000111000001111111
|
||||
size: 32
|
||||
branch: true
|
||||
delay: [1,1]
|
||||
BLT:
|
||||
index: 6
|
||||
encoding: 0b00000000000000000100000001100011
|
||||
mask: 0b00000000000000000111000001111111
|
||||
size: 32
|
||||
branch: true
|
||||
delay: [1,1]
|
||||
BGE:
|
||||
index: 7
|
||||
encoding: 0b00000000000000000101000001100011
|
||||
mask: 0b00000000000000000111000001111111
|
||||
size: 32
|
||||
branch: true
|
||||
delay: [1,1]
|
||||
BLTU:
|
||||
index: 8
|
||||
encoding: 0b00000000000000000110000001100011
|
||||
mask: 0b00000000000000000111000001111111
|
||||
size: 32
|
||||
branch: true
|
||||
delay: [1,1]
|
||||
BGEU:
|
||||
index: 9
|
||||
encoding: 0b00000000000000000111000001100011
|
||||
mask: 0b00000000000000000111000001111111
|
||||
size: 32
|
||||
branch: true
|
||||
delay: [1,1]
|
||||
LB:
|
||||
index: 10
|
||||
encoding: 0b00000000000000000000000000000011
|
||||
mask: 0b00000000000000000111000001111111
|
||||
size: 32
|
||||
branch: false
|
||||
delay: 1
|
||||
LH:
|
||||
index: 11
|
||||
encoding: 0b00000000000000000001000000000011
|
||||
mask: 0b00000000000000000111000001111111
|
||||
size: 32
|
||||
branch: false
|
||||
delay: 1
|
||||
LW:
|
||||
index: 12
|
||||
encoding: 0b00000000000000000010000000000011
|
||||
mask: 0b00000000000000000111000001111111
|
||||
size: 32
|
||||
branch: false
|
||||
delay: 1
|
||||
LBU:
|
||||
index: 13
|
||||
encoding: 0b00000000000000000100000000000011
|
||||
mask: 0b00000000000000000111000001111111
|
||||
size: 32
|
||||
branch: false
|
||||
delay: 1
|
||||
LHU:
|
||||
index: 14
|
||||
encoding: 0b00000000000000000101000000000011
|
||||
mask: 0b00000000000000000111000001111111
|
||||
size: 32
|
||||
branch: false
|
||||
delay: 1
|
||||
SB:
|
||||
index: 15
|
||||
encoding: 0b00000000000000000000000000100011
|
||||
mask: 0b00000000000000000111000001111111
|
||||
size: 32
|
||||
branch: false
|
||||
delay: 1
|
||||
SH:
|
||||
index: 16
|
||||
encoding: 0b00000000000000000001000000100011
|
||||
mask: 0b00000000000000000111000001111111
|
||||
size: 32
|
||||
branch: false
|
||||
delay: 1
|
||||
SW:
|
||||
index: 17
|
||||
encoding: 0b00000000000000000010000000100011
|
||||
mask: 0b00000000000000000111000001111111
|
||||
size: 32
|
||||
branch: false
|
||||
delay: 1
|
||||
ADDI:
|
||||
index: 18
|
||||
encoding: 0b00000000000000000000000000010011
|
||||
mask: 0b00000000000000000111000001111111
|
||||
size: 32
|
||||
branch: false
|
||||
delay: 1
|
||||
SLTI:
|
||||
index: 19
|
||||
encoding: 0b00000000000000000010000000010011
|
||||
mask: 0b00000000000000000111000001111111
|
||||
size: 32
|
||||
branch: false
|
||||
delay: 1
|
||||
SLTIU:
|
||||
index: 20
|
||||
encoding: 0b00000000000000000011000000010011
|
||||
mask: 0b00000000000000000111000001111111
|
||||
size: 32
|
||||
branch: false
|
||||
delay: 1
|
||||
XORI:
|
||||
index: 21
|
||||
encoding: 0b00000000000000000100000000010011
|
||||
mask: 0b00000000000000000111000001111111
|
||||
size: 32
|
||||
branch: false
|
||||
delay: 1
|
||||
ORI:
|
||||
index: 22
|
||||
encoding: 0b00000000000000000110000000010011
|
||||
mask: 0b00000000000000000111000001111111
|
||||
size: 32
|
||||
branch: false
|
||||
delay: 1
|
||||
ANDI:
|
||||
index: 23
|
||||
encoding: 0b00000000000000000111000000010011
|
||||
mask: 0b00000000000000000111000001111111
|
||||
size: 32
|
||||
branch: false
|
||||
delay: 1
|
||||
SLLI:
|
||||
index: 24
|
||||
encoding: 0b00000000000000000001000000010011
|
||||
mask: 0b11111110000000000111000001111111
|
||||
size: 32
|
||||
branch: false
|
||||
delay: 1
|
||||
SRLI:
|
||||
index: 25
|
||||
encoding: 0b00000000000000000101000000010011
|
||||
mask: 0b11111110000000000111000001111111
|
||||
size: 32
|
||||
branch: false
|
||||
delay: 1
|
||||
SRAI:
|
||||
index: 26
|
||||
encoding: 0b01000000000000000101000000010011
|
||||
mask: 0b11111110000000000111000001111111
|
||||
size: 32
|
||||
branch: false
|
||||
delay: 1
|
||||
ADD:
|
||||
index: 27
|
||||
encoding: 0b00000000000000000000000000110011
|
||||
mask: 0b11111110000000000111000001111111
|
||||
size: 32
|
||||
branch: false
|
||||
delay: 1
|
||||
SUB:
|
||||
index: 28
|
||||
encoding: 0b01000000000000000000000000110011
|
||||
mask: 0b11111110000000000111000001111111
|
||||
size: 32
|
||||
branch: false
|
||||
delay: 1
|
||||
SLL:
|
||||
index: 29
|
||||
encoding: 0b00000000000000000001000000110011
|
||||
mask: 0b11111110000000000111000001111111
|
||||
size: 32
|
||||
branch: false
|
||||
delay: 1
|
||||
SLT:
|
||||
index: 30
|
||||
encoding: 0b00000000000000000010000000110011
|
||||
mask: 0b11111110000000000111000001111111
|
||||
size: 32
|
||||
branch: false
|
||||
delay: 1
|
||||
SLTU:
|
||||
index: 31
|
||||
encoding: 0b00000000000000000011000000110011
|
||||
mask: 0b11111110000000000111000001111111
|
||||
size: 32
|
||||
branch: false
|
||||
delay: 1
|
||||
XOR:
|
||||
index: 32
|
||||
encoding: 0b00000000000000000100000000110011
|
||||
mask: 0b11111110000000000111000001111111
|
||||
size: 32
|
||||
branch: false
|
||||
delay: 1
|
||||
SRL:
|
||||
index: 33
|
||||
encoding: 0b00000000000000000101000000110011
|
||||
mask: 0b11111110000000000111000001111111
|
||||
size: 32
|
||||
branch: false
|
||||
delay: 1
|
||||
SRA:
|
||||
index: 34
|
||||
encoding: 0b01000000000000000101000000110011
|
||||
mask: 0b11111110000000000111000001111111
|
||||
size: 32
|
||||
branch: false
|
||||
delay: 1
|
||||
OR:
|
||||
index: 35
|
||||
encoding: 0b00000000000000000110000000110011
|
||||
mask: 0b11111110000000000111000001111111
|
||||
size: 32
|
||||
branch: false
|
||||
delay: 1
|
||||
AND:
|
||||
index: 36
|
||||
encoding: 0b00000000000000000111000000110011
|
||||
mask: 0b11111110000000000111000001111111
|
||||
size: 32
|
||||
branch: false
|
||||
delay: 1
|
||||
FENCE:
|
||||
index: 37
|
||||
encoding: 0b00000000000000000000000000001111
|
||||
mask: 0b00000000000000000111000001111111
|
||||
size: 32
|
||||
branch: false
|
||||
delay: 1
|
||||
ECALL:
|
||||
index: 38
|
||||
encoding: 0b00000000000000000000000001110011
|
||||
mask: 0b11111111111111111111111111111111
|
||||
attributes: [[name:no_cont]]
|
||||
size: 32
|
||||
branch: false
|
||||
delay: 1
|
||||
EBREAK:
|
||||
index: 39
|
||||
encoding: 0b00000000000100000000000001110011
|
||||
mask: 0b11111111111111111111111111111111
|
||||
attributes: [[name:no_cont]]
|
||||
size: 32
|
||||
branch: false
|
||||
delay: 1
|
||||
MRET:
|
||||
index: 40
|
||||
encoding: 0b00110000001000000000000001110011
|
||||
mask: 0b11111111111111111111111111111111
|
||||
attributes: [[name:no_cont]]
|
||||
size: 32
|
||||
branch: false
|
||||
delay: 1
|
||||
WFI:
|
||||
index: 41
|
||||
encoding: 0b00010000010100000000000001110011
|
||||
mask: 0b11111111111111111111111111111111
|
||||
size: 32
|
||||
branch: false
|
||||
delay: 1
|
||||
Zicsr:
|
||||
CSRRW:
|
||||
index: 42
|
||||
encoding: 0b00000000000000000001000001110011
|
||||
mask: 0b00000000000000000111000001111111
|
||||
size: 32
|
||||
branch: false
|
||||
delay: 1
|
||||
CSRRS:
|
||||
index: 43
|
||||
encoding: 0b00000000000000000010000001110011
|
||||
mask: 0b00000000000000000111000001111111
|
||||
size: 32
|
||||
branch: false
|
||||
delay: 1
|
||||
CSRRC:
|
||||
index: 44
|
||||
encoding: 0b00000000000000000011000001110011
|
||||
mask: 0b00000000000000000111000001111111
|
||||
size: 32
|
||||
branch: false
|
||||
delay: 1
|
||||
CSRRWI:
|
||||
index: 45
|
||||
encoding: 0b00000000000000000101000001110011
|
||||
mask: 0b00000000000000000111000001111111
|
||||
size: 32
|
||||
branch: false
|
||||
delay: 1
|
||||
CSRRSI:
|
||||
index: 46
|
||||
encoding: 0b00000000000000000110000001110011
|
||||
mask: 0b00000000000000000111000001111111
|
||||
size: 32
|
||||
branch: false
|
||||
delay: 1
|
||||
CSRRCI:
|
||||
index: 47
|
||||
encoding: 0b00000000000000000111000001110011
|
||||
mask: 0b00000000000000000111000001111111
|
||||
size: 32
|
||||
branch: false
|
||||
delay: 1
|
||||
Zifencei:
|
||||
FENCE_I:
|
||||
index: 48
|
||||
encoding: 0b00000000000000000001000000001111
|
||||
mask: 0b00000000000000000111000001111111
|
||||
attributes: [[name:flush]]
|
||||
size: 32
|
||||
branch: false
|
||||
delay: 1
|
||||
RV32M:
|
||||
MUL:
|
||||
index: 49
|
||||
encoding: 0b00000010000000000000000000110011
|
||||
mask: 0b11111110000000000111000001111111
|
||||
size: 32
|
||||
branch: false
|
||||
delay: 1
|
||||
MULH:
|
||||
index: 50
|
||||
encoding: 0b00000010000000000001000000110011
|
||||
mask: 0b11111110000000000111000001111111
|
||||
size: 32
|
||||
branch: false
|
||||
delay: 1
|
||||
MULHSU:
|
||||
index: 51
|
||||
encoding: 0b00000010000000000010000000110011
|
||||
mask: 0b11111110000000000111000001111111
|
||||
size: 32
|
||||
branch: false
|
||||
delay: 1
|
||||
MULHU:
|
||||
index: 52
|
||||
encoding: 0b00000010000000000011000000110011
|
||||
mask: 0b11111110000000000111000001111111
|
||||
size: 32
|
||||
branch: false
|
||||
delay: 1
|
||||
DIV:
|
||||
index: 53
|
||||
encoding: 0b00000010000000000100000000110011
|
||||
mask: 0b11111110000000000111000001111111
|
||||
size: 32
|
||||
branch: false
|
||||
delay: 1
|
||||
DIVU:
|
||||
index: 54
|
||||
encoding: 0b00000010000000000101000000110011
|
||||
mask: 0b11111110000000000111000001111111
|
||||
size: 32
|
||||
branch: false
|
||||
delay: 1
|
||||
REM:
|
||||
index: 55
|
||||
encoding: 0b00000010000000000110000000110011
|
||||
mask: 0b11111110000000000111000001111111
|
||||
size: 32
|
||||
branch: false
|
||||
delay: 1
|
||||
REMU:
|
||||
index: 56
|
||||
encoding: 0b00000010000000000111000000110011
|
||||
mask: 0b11111110000000000111000001111111
|
||||
size: 32
|
||||
branch: false
|
||||
delay: 1
|
||||
Zca:
|
||||
C__ADDI4SPN:
|
||||
index: 57
|
||||
encoding: 0b0000000000000000
|
||||
mask: 0b1110000000000011
|
||||
size: 16
|
||||
branch: false
|
||||
delay: 1
|
||||
C__LW:
|
||||
index: 58
|
||||
encoding: 0b0100000000000000
|
||||
mask: 0b1110000000000011
|
||||
size: 16
|
||||
branch: false
|
||||
delay: 1
|
||||
C__SW:
|
||||
index: 59
|
||||
encoding: 0b1100000000000000
|
||||
mask: 0b1110000000000011
|
||||
size: 16
|
||||
branch: false
|
||||
delay: 1
|
||||
C__ADDI:
|
||||
index: 60
|
||||
encoding: 0b0000000000000001
|
||||
mask: 0b1110000000000011
|
||||
size: 16
|
||||
branch: false
|
||||
delay: 1
|
||||
C__NOP:
|
||||
index: 61
|
||||
encoding: 0b0000000000000001
|
||||
mask: 0b1110111110000011
|
||||
size: 16
|
||||
branch: false
|
||||
delay: 1
|
||||
C__JAL:
|
||||
index: 62
|
||||
encoding: 0b0010000000000001
|
||||
mask: 0b1110000000000011
|
||||
attributes: [[name:enable, value:1]]
|
||||
size: 16
|
||||
branch: true
|
||||
delay: 1
|
||||
C__LI:
|
||||
index: 63
|
||||
encoding: 0b0100000000000001
|
||||
mask: 0b1110000000000011
|
||||
size: 16
|
||||
branch: false
|
||||
delay: 1
|
||||
C__LUI:
|
||||
index: 64
|
||||
encoding: 0b0110000000000001
|
||||
mask: 0b1110000000000011
|
||||
size: 16
|
||||
branch: false
|
||||
delay: 1
|
||||
C__ADDI16SP:
|
||||
index: 65
|
||||
encoding: 0b0110000100000001
|
||||
mask: 0b1110111110000011
|
||||
size: 16
|
||||
branch: false
|
||||
delay: 1
|
||||
__reserved_clui:
|
||||
index: 66
|
||||
encoding: 0b0110000000000001
|
||||
mask: 0b1111000001111111
|
||||
size: 16
|
||||
branch: false
|
||||
delay: 1
|
||||
C__SRLI:
|
||||
index: 67
|
||||
encoding: 0b1000000000000001
|
||||
mask: 0b1111110000000011
|
||||
attributes: [[name:enable, value:1]]
|
||||
size: 16
|
||||
branch: false
|
||||
delay: 1
|
||||
C__SRAI:
|
||||
index: 68
|
||||
encoding: 0b1000010000000001
|
||||
mask: 0b1111110000000011
|
||||
attributes: [[name:enable, value:1]]
|
||||
size: 16
|
||||
branch: false
|
||||
delay: 1
|
||||
C__ANDI:
|
||||
index: 69
|
||||
encoding: 0b1000100000000001
|
||||
mask: 0b1110110000000011
|
||||
size: 16
|
||||
branch: false
|
||||
delay: 1
|
||||
C__SUB:
|
||||
index: 70
|
||||
encoding: 0b1000110000000001
|
||||
mask: 0b1111110001100011
|
||||
size: 16
|
||||
branch: false
|
||||
delay: 1
|
||||
C__XOR:
|
||||
index: 71
|
||||
encoding: 0b1000110000100001
|
||||
mask: 0b1111110001100011
|
||||
size: 16
|
||||
branch: false
|
||||
delay: 1
|
||||
C__OR:
|
||||
index: 72
|
||||
encoding: 0b1000110001000001
|
||||
mask: 0b1111110001100011
|
||||
size: 16
|
||||
branch: false
|
||||
delay: 1
|
||||
C__AND:
|
||||
index: 73
|
||||
encoding: 0b1000110001100001
|
||||
mask: 0b1111110001100011
|
||||
size: 16
|
||||
branch: false
|
||||
delay: 1
|
||||
C__J:
|
||||
index: 74
|
||||
encoding: 0b1010000000000001
|
||||
mask: 0b1110000000000011
|
||||
size: 16
|
||||
branch: true
|
||||
delay: 1
|
||||
C__BEQZ:
|
||||
index: 75
|
||||
encoding: 0b1100000000000001
|
||||
mask: 0b1110000000000011
|
||||
size: 16
|
||||
branch: true
|
||||
delay: [1,1]
|
||||
C__BNEZ:
|
||||
index: 76
|
||||
encoding: 0b1110000000000001
|
||||
mask: 0b1110000000000011
|
||||
size: 16
|
||||
branch: true
|
||||
delay: [1,1]
|
||||
C__SLLI:
|
||||
index: 77
|
||||
encoding: 0b0000000000000010
|
||||
mask: 0b1111000000000011
|
||||
attributes: [[name:enable, value:1]]
|
||||
size: 16
|
||||
branch: false
|
||||
delay: 1
|
||||
C__LWSP:
|
||||
index: 78
|
||||
encoding: 0b0100000000000010
|
||||
mask: 0b1110000000000011
|
||||
size: 16
|
||||
branch: false
|
||||
delay: 1
|
||||
C__MV:
|
||||
index: 79
|
||||
encoding: 0b1000000000000010
|
||||
mask: 0b1111000000000011
|
||||
size: 16
|
||||
branch: false
|
||||
delay: 1
|
||||
C__JR:
|
||||
index: 80
|
||||
encoding: 0b1000000000000010
|
||||
mask: 0b1111000001111111
|
||||
size: 16
|
||||
branch: true
|
||||
delay: 1
|
||||
__reserved_cmv:
|
||||
index: 81
|
||||
encoding: 0b1000000000000010
|
||||
mask: 0b1111111111111111
|
||||
size: 16
|
||||
branch: false
|
||||
delay: 1
|
||||
C__ADD:
|
||||
index: 82
|
||||
encoding: 0b1001000000000010
|
||||
mask: 0b1111000000000011
|
||||
size: 16
|
||||
branch: false
|
||||
delay: 1
|
||||
C__JALR:
|
||||
index: 83
|
||||
encoding: 0b1001000000000010
|
||||
mask: 0b1111000001111111
|
||||
size: 16
|
||||
branch: true
|
||||
delay: 1
|
||||
C__EBREAK:
|
||||
index: 84
|
||||
encoding: 0b1001000000000010
|
||||
mask: 0b1111111111111111
|
||||
size: 16
|
||||
branch: false
|
||||
delay: 1
|
||||
C__SWSP:
|
||||
index: 85
|
||||
encoding: 0b1100000000000010
|
||||
mask: 0b1110000000000011
|
||||
size: 16
|
||||
branch: false
|
||||
delay: 1
|
||||
DII:
|
||||
index: 86
|
||||
encoding: 0b0000000000000000
|
||||
mask: 0b1111111111111111
|
||||
size: 16
|
||||
branch: false
|
||||
delay: 1
|
||||
|
|
@ -0,0 +1,650 @@
|
|||
RV32I:
|
||||
ADD:
|
||||
branch: false
|
||||
delay: 1
|
||||
encoding: 51
|
||||
index: 27
|
||||
mask: 4261441663
|
||||
size: 32
|
||||
ADDI:
|
||||
branch: false
|
||||
delay: 1
|
||||
encoding: 19
|
||||
index: 18
|
||||
mask: 28799
|
||||
size: 32
|
||||
AND:
|
||||
branch: false
|
||||
delay: 1
|
||||
encoding: 28723
|
||||
index: 36
|
||||
mask: 4261441663
|
||||
size: 32
|
||||
ANDI:
|
||||
branch: false
|
||||
delay: 1
|
||||
encoding: 28691
|
||||
index: 23
|
||||
mask: 28799
|
||||
size: 32
|
||||
AUIPC:
|
||||
branch: false
|
||||
delay: 1
|
||||
encoding: 23
|
||||
index: 1
|
||||
mask: 127
|
||||
size: 32
|
||||
BEQ:
|
||||
branch: true
|
||||
delay:
|
||||
- 1
|
||||
- 2
|
||||
encoding: 99
|
||||
index: 4
|
||||
mask: 28799
|
||||
size: 32
|
||||
BGE:
|
||||
branch: true
|
||||
delay:
|
||||
- 1
|
||||
- 2
|
||||
encoding: 20579
|
||||
index: 7
|
||||
mask: 28799
|
||||
size: 32
|
||||
BGEU:
|
||||
branch: true
|
||||
delay:
|
||||
- 1
|
||||
- 2
|
||||
encoding: 28771
|
||||
index: 9
|
||||
mask: 28799
|
||||
size: 32
|
||||
BLT:
|
||||
branch: true
|
||||
delay:
|
||||
- 1
|
||||
- 2
|
||||
encoding: 16483
|
||||
index: 6
|
||||
mask: 28799
|
||||
size: 32
|
||||
BLTU:
|
||||
branch: true
|
||||
delay:
|
||||
- 1
|
||||
- 2
|
||||
encoding: 24675
|
||||
index: 8
|
||||
mask: 28799
|
||||
size: 32
|
||||
BNE:
|
||||
branch: true
|
||||
delay:
|
||||
- 1
|
||||
- 2
|
||||
encoding: 4195
|
||||
index: 5
|
||||
mask: 28799
|
||||
size: 32
|
||||
EBREAK:
|
||||
attributes:
|
||||
- - name:no_cont
|
||||
branch: false
|
||||
delay: 3
|
||||
encoding: 1048691
|
||||
index: 39
|
||||
mask: 4294967295
|
||||
size: 32
|
||||
ECALL:
|
||||
attributes:
|
||||
- - name:no_cont
|
||||
branch: false
|
||||
delay: 1
|
||||
encoding: 115
|
||||
index: 38
|
||||
mask: 4294967295
|
||||
size: 32
|
||||
FENCE:
|
||||
branch: false
|
||||
delay: 1
|
||||
encoding: 15
|
||||
index: 37
|
||||
mask: 28799
|
||||
size: 32
|
||||
JAL:
|
||||
branch: true
|
||||
delay: 2
|
||||
encoding: 111
|
||||
index: 2
|
||||
mask: 127
|
||||
size: 32
|
||||
JALR:
|
||||
branch: true
|
||||
delay: 2
|
||||
encoding: 103
|
||||
index: 3
|
||||
mask: 28799
|
||||
size: 32
|
||||
LB:
|
||||
branch: false
|
||||
delay: 2
|
||||
encoding: 3
|
||||
index: 10
|
||||
mask: 28799
|
||||
size: 32
|
||||
LBU:
|
||||
branch: false
|
||||
delay: 2
|
||||
encoding: 16387
|
||||
index: 13
|
||||
mask: 28799
|
||||
size: 32
|
||||
LH:
|
||||
branch: false
|
||||
delay: 2
|
||||
encoding: 4099
|
||||
index: 11
|
||||
mask: 28799
|
||||
size: 32
|
||||
LHU:
|
||||
branch: false
|
||||
delay: 2
|
||||
encoding: 20483
|
||||
index: 14
|
||||
mask: 28799
|
||||
size: 32
|
||||
LUI:
|
||||
branch: false
|
||||
delay: 1
|
||||
encoding: 55
|
||||
index: 0
|
||||
mask: 127
|
||||
size: 32
|
||||
LW:
|
||||
branch: false
|
||||
delay: 2
|
||||
encoding: 8195
|
||||
index: 12
|
||||
mask: 28799
|
||||
size: 32
|
||||
MRET:
|
||||
attributes:
|
||||
- - name:no_cont
|
||||
branch: false
|
||||
delay: 2
|
||||
encoding: 807403635
|
||||
index: 40
|
||||
mask: 4294967295
|
||||
size: 32
|
||||
OR:
|
||||
branch: false
|
||||
delay: 1
|
||||
encoding: 24627
|
||||
index: 35
|
||||
mask: 4261441663
|
||||
size: 32
|
||||
ORI:
|
||||
branch: false
|
||||
delay: 1
|
||||
encoding: 24595
|
||||
index: 22
|
||||
mask: 28799
|
||||
size: 32
|
||||
SB:
|
||||
branch: false
|
||||
delay: 1
|
||||
encoding: 35
|
||||
index: 15
|
||||
mask: 28799
|
||||
size: 32
|
||||
SH:
|
||||
branch: false
|
||||
delay: 1
|
||||
encoding: 4131
|
||||
index: 16
|
||||
mask: 28799
|
||||
size: 32
|
||||
SLL:
|
||||
branch: false
|
||||
delay: X_24:20
|
||||
encoding: 4147
|
||||
index: 29
|
||||
mask: 4261441663
|
||||
size: 32
|
||||
SLLI:
|
||||
branch: false
|
||||
delay: u_24:20
|
||||
encoding: 4115
|
||||
index: 24
|
||||
mask: 4261441663
|
||||
size: 32
|
||||
SLT:
|
||||
branch: false
|
||||
delay: 1
|
||||
encoding: 8243
|
||||
index: 30
|
||||
mask: 4261441663
|
||||
size: 32
|
||||
SLTI:
|
||||
branch: false
|
||||
delay: 1
|
||||
encoding: 8211
|
||||
index: 19
|
||||
mask: 28799
|
||||
size: 32
|
||||
SLTIU:
|
||||
branch: false
|
||||
delay: 1
|
||||
encoding: 12307
|
||||
index: 20
|
||||
mask: 28799
|
||||
size: 32
|
||||
SLTU:
|
||||
branch: false
|
||||
delay: 1
|
||||
encoding: 12339
|
||||
index: 31
|
||||
mask: 4261441663
|
||||
size: 32
|
||||
SRA:
|
||||
branch: false
|
||||
delay: X_24:20
|
||||
encoding: 1073762355
|
||||
index: 34
|
||||
mask: 4261441663
|
||||
size: 32
|
||||
SRAI:
|
||||
branch: false
|
||||
delay: u_24:20
|
||||
encoding: 1073762323
|
||||
index: 26
|
||||
mask: 4261441663
|
||||
size: 32
|
||||
SRL:
|
||||
branch: false
|
||||
delay: X_24:20
|
||||
encoding: 20531
|
||||
index: 33
|
||||
mask: 4261441663
|
||||
size: 32
|
||||
SRLI:
|
||||
branch: false
|
||||
delay: u_24:20
|
||||
encoding: 20499
|
||||
index: 25
|
||||
mask: 4261441663
|
||||
size: 32
|
||||
SUB:
|
||||
branch: false
|
||||
delay: 1
|
||||
encoding: 1073741875
|
||||
index: 28
|
||||
mask: 4261441663
|
||||
size: 32
|
||||
SW:
|
||||
branch: false
|
||||
delay: 1
|
||||
encoding: 8227
|
||||
index: 17
|
||||
mask: 28799
|
||||
size: 32
|
||||
WFI:
|
||||
branch: false
|
||||
delay: 1
|
||||
encoding: 273678451
|
||||
index: 41
|
||||
mask: 4294967295
|
||||
size: 32
|
||||
XOR:
|
||||
branch: false
|
||||
delay: 1
|
||||
encoding: 16435
|
||||
index: 32
|
||||
mask: 4261441663
|
||||
size: 32
|
||||
XORI:
|
||||
branch: false
|
||||
delay: 1
|
||||
encoding: 16403
|
||||
index: 21
|
||||
mask: 28799
|
||||
size: 32
|
||||
RV32M:
|
||||
DIV:
|
||||
branch: false
|
||||
delay: 33
|
||||
encoding: 33570867
|
||||
index: 53
|
||||
mask: 4261441663
|
||||
size: 32
|
||||
DIVU:
|
||||
branch: false
|
||||
delay: 33
|
||||
encoding: 33574963
|
||||
index: 54
|
||||
mask: 4261441663
|
||||
size: 32
|
||||
MUL:
|
||||
branch: false
|
||||
delay: 32
|
||||
encoding: 33554483
|
||||
index: 49
|
||||
mask: 4261441663
|
||||
size: 32
|
||||
MULH:
|
||||
branch: false
|
||||
delay: 32
|
||||
encoding: 33558579
|
||||
index: 50
|
||||
mask: 4261441663
|
||||
size: 32
|
||||
MULHSU:
|
||||
branch: false
|
||||
delay: 32
|
||||
encoding: 33562675
|
||||
index: 51
|
||||
mask: 4261441663
|
||||
size: 32
|
||||
MULHU:
|
||||
branch: false
|
||||
delay: 32
|
||||
encoding: 33566771
|
||||
index: 52
|
||||
mask: 4261441663
|
||||
size: 32
|
||||
REM:
|
||||
branch: false
|
||||
delay: 33
|
||||
encoding: 33579059
|
||||
index: 55
|
||||
mask: 4261441663
|
||||
size: 32
|
||||
REMU:
|
||||
branch: false
|
||||
delay: 33
|
||||
encoding: 33583155
|
||||
index: 56
|
||||
mask: 4261441663
|
||||
size: 32
|
||||
Zca:
|
||||
C__ADD:
|
||||
branch: false
|
||||
delay: 1
|
||||
encoding: 36866
|
||||
index: 82
|
||||
mask: 61443
|
||||
size: 16
|
||||
C__ADDI:
|
||||
branch: false
|
||||
delay: 1
|
||||
encoding: 1
|
||||
index: 60
|
||||
mask: 57347
|
||||
size: 16
|
||||
C__ADDI16SP:
|
||||
branch: false
|
||||
delay: 1
|
||||
encoding: 24833
|
||||
index: 65
|
||||
mask: 61315
|
||||
size: 16
|
||||
C__ADDI4SPN:
|
||||
branch: false
|
||||
delay: 1
|
||||
encoding: 0
|
||||
index: 57
|
||||
mask: 57347
|
||||
size: 16
|
||||
C__AND:
|
||||
branch: false
|
||||
delay: 1
|
||||
encoding: 35937
|
||||
index: 73
|
||||
mask: 64611
|
||||
size: 16
|
||||
C__ANDI:
|
||||
branch: false
|
||||
delay: 1
|
||||
encoding: 34817
|
||||
index: 69
|
||||
mask: 60419
|
||||
size: 16
|
||||
C__BEQZ:
|
||||
branch: true
|
||||
delay:
|
||||
- 1
|
||||
- 2
|
||||
encoding: 49153
|
||||
index: 75
|
||||
mask: 57347
|
||||
size: 16
|
||||
C__BNEZ:
|
||||
branch: true
|
||||
delay:
|
||||
- 1
|
||||
- 2
|
||||
encoding: 57345
|
||||
index: 76
|
||||
mask: 57347
|
||||
size: 16
|
||||
C__EBREAK:
|
||||
branch: false
|
||||
delay: 3
|
||||
encoding: 36866
|
||||
index: 84
|
||||
mask: 65535
|
||||
size: 16
|
||||
C__J:
|
||||
branch: true
|
||||
delay: 1
|
||||
encoding: 40961
|
||||
index: 74
|
||||
mask: 57347
|
||||
size: 16
|
||||
C__JAL:
|
||||
attributes:
|
||||
- - name:enable
|
||||
- value:1
|
||||
branch: true
|
||||
delay: 1
|
||||
encoding: 8193
|
||||
index: 62
|
||||
mask: 57347
|
||||
size: 16
|
||||
C__JALR:
|
||||
branch: true
|
||||
delay: 1
|
||||
encoding: 36866
|
||||
index: 83
|
||||
mask: 61567
|
||||
size: 16
|
||||
C__JR:
|
||||
branch: true
|
||||
delay: 1
|
||||
encoding: 32770
|
||||
index: 80
|
||||
mask: 61567
|
||||
size: 16
|
||||
C__LI:
|
||||
branch: false
|
||||
delay: 1
|
||||
encoding: 16385
|
||||
index: 63
|
||||
mask: 57347
|
||||
size: 16
|
||||
C__LUI:
|
||||
branch: false
|
||||
delay: 1
|
||||
encoding: 24577
|
||||
index: 64
|
||||
mask: 57347
|
||||
size: 16
|
||||
C__LW:
|
||||
branch: false
|
||||
delay: 2
|
||||
encoding: 16384
|
||||
index: 58
|
||||
mask: 57347
|
||||
size: 16
|
||||
C__LWSP:
|
||||
branch: false
|
||||
delay: 2
|
||||
encoding: 16386
|
||||
index: 78
|
||||
mask: 57347
|
||||
size: 16
|
||||
C__MV:
|
||||
branch: false
|
||||
delay: 1
|
||||
encoding: 32770
|
||||
index: 79
|
||||
mask: 61443
|
||||
size: 16
|
||||
C__NOP:
|
||||
branch: false
|
||||
delay: 1
|
||||
encoding: 1
|
||||
index: 61
|
||||
mask: 61315
|
||||
size: 16
|
||||
C__OR:
|
||||
branch: false
|
||||
delay: 1
|
||||
encoding: 35905
|
||||
index: 72
|
||||
mask: 64611
|
||||
size: 16
|
||||
C__SLLI:
|
||||
attributes:
|
||||
- - name:enable
|
||||
- value:1
|
||||
branch: false
|
||||
delay: u_12:12*16+u_6:2
|
||||
encoding: 2
|
||||
index: 77
|
||||
mask: 61443
|
||||
size: 16
|
||||
C__SRAI:
|
||||
attributes:
|
||||
- - name:enable
|
||||
- value:1
|
||||
branch: false
|
||||
delay: u_12:12*16+u_6:2
|
||||
encoding: 33793
|
||||
index: 68
|
||||
mask: 64515
|
||||
size: 16
|
||||
C__SRLI:
|
||||
attributes:
|
||||
- - name:enable
|
||||
- value:1
|
||||
branch: false
|
||||
delay: u_12:12*16+u_6:2
|
||||
encoding: 32769
|
||||
index: 67
|
||||
mask: 64515
|
||||
size: 16
|
||||
C__SUB:
|
||||
branch: false
|
||||
delay: 1
|
||||
encoding: 35841
|
||||
index: 70
|
||||
mask: 64611
|
||||
size: 16
|
||||
C__SW:
|
||||
branch: false
|
||||
delay: 1
|
||||
encoding: 49152
|
||||
index: 59
|
||||
mask: 57347
|
||||
size: 16
|
||||
C__SWSP:
|
||||
branch: false
|
||||
delay: 1
|
||||
encoding: 49154
|
||||
index: 85
|
||||
mask: 57347
|
||||
size: 16
|
||||
C__XOR:
|
||||
branch: false
|
||||
delay: 1
|
||||
encoding: 35873
|
||||
index: 71
|
||||
mask: 64611
|
||||
size: 16
|
||||
DII:
|
||||
branch: false
|
||||
delay: 1
|
||||
encoding: 0
|
||||
index: 86
|
||||
mask: 65535
|
||||
size: 16
|
||||
__reserved_clui:
|
||||
branch: false
|
||||
delay: 1
|
||||
encoding: 24577
|
||||
index: 66
|
||||
mask: 61567
|
||||
size: 16
|
||||
__reserved_cmv:
|
||||
branch: false
|
||||
delay: 1
|
||||
encoding: 32770
|
||||
index: 81
|
||||
mask: 65535
|
||||
size: 16
|
||||
Zicsr:
|
||||
CSRRC:
|
||||
branch: false
|
||||
delay: 1
|
||||
encoding: 12403
|
||||
index: 44
|
||||
mask: 28799
|
||||
size: 32
|
||||
CSRRCI:
|
||||
branch: false
|
||||
delay: 1
|
||||
encoding: 28787
|
||||
index: 47
|
||||
mask: 28799
|
||||
size: 32
|
||||
CSRRS:
|
||||
branch: false
|
||||
delay: 1
|
||||
encoding: 8307
|
||||
index: 43
|
||||
mask: 28799
|
||||
size: 32
|
||||
CSRRSI:
|
||||
branch: false
|
||||
delay: 1
|
||||
encoding: 24691
|
||||
index: 46
|
||||
mask: 28799
|
||||
size: 32
|
||||
CSRRW:
|
||||
branch: false
|
||||
delay: 1
|
||||
encoding: 4211
|
||||
index: 42
|
||||
mask: 28799
|
||||
size: 32
|
||||
CSRRWI:
|
||||
branch: false
|
||||
delay: 1
|
||||
encoding: 20595
|
||||
index: 45
|
||||
mask: 28799
|
||||
size: 32
|
||||
Zifencei:
|
||||
FENCE_I:
|
||||
attributes:
|
||||
- - name:flush
|
||||
branch: false
|
||||
delay: 1
|
||||
encoding: 4111
|
||||
index: 48
|
||||
mask: 28799
|
||||
size: 32
|
|
@ -0,0 +1,3 @@
|
|||
/results
|
||||
/cwr
|
||||
/*.xml
|
|
@ -0,0 +1,43 @@
|
|||
# Notes
|
||||
|
||||
* requires conan version 1.59
|
||||
* requires decent cmake version 3.23
|
||||
|
||||
Setup for tcsh:
|
||||
|
||||
```
|
||||
git clone --recursive -b develop https://git.minres.com/TGFS/TGC-ISS.git
|
||||
cd TGC-ISS/
|
||||
setenv TGFS_INSTALL_ROOT `pwd`/install
|
||||
setenv COWAREHOME <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
|
||||
```
|
|
@ -16,7 +16,7 @@ namespace eval Specification {
|
|||
set libdir "${install_dir}/lib64"
|
||||
set preprocessorOptions [concat $preprocessorOptions "-I${incldir}"]
|
||||
# Set the Linker paths.
|
||||
set linkerOptions [concat $linkerOptions "-Wl,-rpath,${libdir} -L${libdir} -ldbt-rise-tgc_sc"]
|
||||
set linkerOptions [concat $linkerOptions "-Wl,-rpath,${libdir} -L${libdir} -ldbt-rise-tgc_sc -lscc-sysc"]
|
||||
}
|
||||
default {
|
||||
puts stderr "ERROR: \"$target\" is not supported, [::scsh::version]"
|
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
After Width: | Height: | Size: 25 KiB |
|
@ -6,14 +6,11 @@ proc getScriptDirectory {} {
|
|||
set scriptFolder [file dirname $dispScriptFile]
|
||||
return $scriptFolder
|
||||
}
|
||||
if { $::env(SNPS_VP_PRODUCT) == "PAULTRA" } {
|
||||
set hardware /HARDWARE/HW/HW
|
||||
} else {
|
||||
set hardware /HARDWARE
|
||||
}
|
||||
|
||||
set scriptDir [getScriptDirectory]
|
||||
set top_design_name core_complex
|
||||
set encap_name sysc::tgfs::${top_design_name}
|
||||
set clocks clk_i
|
||||
set resets rst_i
|
||||
set model_prefix "i_"
|
||||
|
@ -28,7 +25,8 @@ set model_postfix ""
|
|||
::pct::set_update_existing_encaps_flag true
|
||||
::pct::set_dynamic_port_arrays_flag true
|
||||
::pct::set_import_scml_properties_flag true
|
||||
::pct::load_modules --set-category modules tgc_import.cc
|
||||
::pct::set_import_encap_prop_as_extra_prop_flag true
|
||||
::pct::load_modules --set-category modules ${scriptDir}/tgc_import.cc
|
||||
|
||||
# Set Port Protocols correctly
|
||||
set block ${top_design_name}
|
||||
|
@ -38,13 +36,15 @@ foreach clock ${clocks} {
|
|||
foreach reset ${resets} {
|
||||
::pct::set_block_port_protocol --set-category SYSTEM_LIBRARY:$block/${reset} SYSTEM_LIBRARY:RESET
|
||||
}
|
||||
::pct::set_encap_port_array_size SYSTEM_LIBRARY:$block/local_irq_i 16
|
||||
#::pct::set_encap_port_array_size SYSTEM_LIBRARY:$block/local_irq_i 16
|
||||
|
||||
# Set compile settings and look
|
||||
set block SYSTEM_LIBRARY:${top_design_name}
|
||||
::pct::set_encap_build_script $block/${top_design_name} $scriptDir/build.tcl
|
||||
::pct::set_encap_build_script $block/${encap_name} $scriptDir/build.tcl
|
||||
::pct::set_background_color_rgb $block 255 255 255 255
|
||||
::pct::create_instance SYSTEM_LIBRARY:${top_design_name} ${hardware} ${model_prefix}${top_design_name}${model_postfix} ${top_design_name}
|
||||
::pct::create_instance SYSTEM_LIBRARY:${top_design_name} ${hardware} ${model_prefix}${top_design_name}${model_postfix} ${encap_name} ${encap_name}()
|
||||
::pct::set_bounds i_${top_design_name} 200 300 100 400
|
||||
::pct::set_image i_${top_design_name} "$scriptDir/minres.png" center center false true
|
||||
|
||||
# export the result as component
|
||||
::pct::export_system_library ${top_design_name} ${top_design_name}.xml
|
|
@ -0,0 +1,71 @@
|
|||
source tgc_import.tcl
|
||||
set hardware /HARDWARE/HW/HW
|
||||
set FW_name ${scriptDir}/hello.elf
|
||||
|
||||
puts "instantiate testbench elements"
|
||||
::paultra::add_hw_instance GenericIPlib:Memory_Generic -inst_name i_Memory_Generic
|
||||
::pct::set_param_value i_Memory_Generic/MEM:protocol {Protocol Common Parameters} address_width 30
|
||||
::pct::set_param_value i_Memory_Generic {Scml Properties} /timing/LT/clock_period_in_ns 1
|
||||
::pct::set_param_value i_Memory_Generic {Scml Properties} /timing/read/cmd_accept_cycles 1
|
||||
::pct::set_param_value i_Memory_Generic {Scml Properties} /timing/write/cmd_accept_cycles 1
|
||||
::pct::set_bounds i_Memory_Generic 1000 300 100 100
|
||||
|
||||
::paultra::add_hw_instance Bus:Bus -inst_name i_Bus
|
||||
::BLWizard::generateFramework i_Bus SBLTLM2FT * {} \
|
||||
{ common_configuration:BackBone:/advanced/num_resources_per_target:1 }
|
||||
::pct::set_bounds i_Bus 700 300 100 400
|
||||
::pct::create_connection C_ibus i_core_complex/ibus i_Bus/i_core_complex_ibus
|
||||
::pct::set_location_on_owner i_Bus/i_core_complex_ibus 10
|
||||
::pct::create_connection C_dbus i_core_complex/dbus i_Bus/i_core_complex_dbus
|
||||
::pct::set_location_on_owner i_Bus/i_core_complex_dbus 10
|
||||
::pct::create_connection C_mem i_Bus/i_Memory_Generic_MEM i_Memory_Generic/MEM
|
||||
|
||||
puts "instantiating clock manager"
|
||||
set clock "Clk"
|
||||
::hw::create_hw_instance "" GenericIPlib:ClockGenerator ${clock}_clock
|
||||
::pct::set_bounds ${clock}_clock 100 100 100 100
|
||||
::pct::set_param_value $hardware/${clock}_clock {Constructor Arguments} period 1000
|
||||
::pct::set_param_value $hardware/${clock}_clock {Constructor Arguments} period_unit sc_core::SC_PS
|
||||
|
||||
puts "instantiating reset manager"
|
||||
set reset "Rst"
|
||||
::hw::create_hw_instance "" GenericIPlib:ResetGenerator ${reset}_reset
|
||||
::pct::set_param_value $hardware/${reset}_reset {Constructor Arguments} start_time 0
|
||||
::pct::set_param_value $hardware/${reset}_reset {Constructor Arguments} start_time_unit sc_core::SC_PS
|
||||
::pct::set_param_value $hardware/${reset}_reset {Constructor Arguments} duration 10000
|
||||
::pct::set_param_value $hardware/${reset}_reset {Constructor Arguments} duration_unit sc_core::SC_PS
|
||||
::pct::set_param_value $hardware/${reset}_reset {Constructor Arguments} active_level true
|
||||
::pct::set_bounds ${reset}_reset 300 100 100 100
|
||||
|
||||
puts "connecting reset/clock"
|
||||
::pct::create_connection C_clk . Clk_clock/CLK i_core_complex/clk_i
|
||||
::pct::add_ports_to_connection C_clk i_Bus/Clk
|
||||
::pct::add_ports_to_connection C_clk i_Memory_Generic/CLK
|
||||
::pct::create_connection C_rst . Rst_reset/RST i_core_complex/rst_i
|
||||
::pct::add_ports_to_connection C_rst i_Bus/Rst
|
||||
|
||||
puts "setting parameters for DBT-RISE-TGC/Bus and memory components"
|
||||
::pct::set_param_value $hardware/i_${top_design_name} {Extra properties} elf_file ${FW_name}
|
||||
::pct::set_address $hardware/i_${top_design_name}/ibus:i_Memory_Generic/MEM 0x0
|
||||
::pct::set_address $hardware/i_${top_design_name}/dbus:i_Memory_Generic/MEM 0x0
|
||||
::BLWizard::updateFramework i_Bus {} { common_configuration:BackBone:/advanced/num_resources_per_target:1 }
|
||||
|
||||
::pct::set_main_configuration Default {{#include <scc/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
|
|
@ -0,0 +1,13 @@
|
|||
import "ISA/RVI.core_desc"
|
||||
import "ISA/RVM.core_desc"
|
||||
import "ISA/RVC.core_desc"
|
||||
|
||||
Core TGC5C provides RV32I, Zicsr, Zifencei, RV32M, RV32IC {
|
||||
architectural_state {
|
||||
XLEN=32;
|
||||
// definitions for the architecture wrapper
|
||||
// XL ZYXWVUTSRQPONMLKJIHGFEDCBA
|
||||
unsigned int MISA_VAL = 0b01000000000000000001000100000100;
|
||||
unsigned int MARCHID_VAL = 0x80000003;
|
||||
}
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
import "CoreDSL-Instruction-Set-Description/RV32I.core_desc"
|
||||
import "CoreDSL-Instruction-Set-Description/RVM.core_desc"
|
||||
import "CoreDSL-Instruction-Set-Description/RVC.core_desc"
|
||||
|
||||
Core TGC_C provides RV32I, Zicsr, Zifencei, RV32M, RV32IC {
|
||||
architectural_state {
|
||||
XLEN=32;
|
||||
// definitions for the architecture wrapper
|
||||
// XL ZYXWVUTSRQPONMLKJIHGFEDCBA
|
||||
unsigned MISA_VAL = 0b01000000000000000001000100000100;
|
||||
unsigned MARCHID_VAL = 0x80000003;
|
||||
}
|
||||
}
|
|
@ -33,13 +33,14 @@
|
|||
def getRegisterSizes(){
|
||||
def regs = registers.collect{it.size}
|
||||
regs[-1]=64 // correct for NEXT_PC
|
||||
regs+=[32, 32, 64, 64, 64] // append TRAP_STATE, PENDING_TRAP, ICOUNT, CYCLE, INSTRET
|
||||
regs+=[32,32, 64, 64, 64, 32, 32] // append TRAP_STATE, PENDING_TRAP, ICOUNT, CYCLE, INSTRET, INSTRUCTION, LAST_BRANCH
|
||||
return regs
|
||||
}
|
||||
%>
|
||||
// clang-format off
|
||||
#include "${coreDef.name.toLowerCase()}.h"
|
||||
#include "util/ities.h"
|
||||
#include <util/logging.h>
|
||||
#include <iss/arch/${coreDef.name.toLowerCase()}.h>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <fstream>
|
||||
|
@ -51,9 +52,7 @@ constexpr std::array<const char*, ${registers.size}> iss::arch::traits<iss::a
|
|||
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;
|
||||
|
||||
${coreDef.name.toLowerCase()}::${coreDef.name.toLowerCase()}() {
|
||||
reg.icount = 0;
|
||||
}
|
||||
${coreDef.name.toLowerCase()}::${coreDef.name.toLowerCase()}() = default;
|
||||
|
||||
${coreDef.name.toLowerCase()}::~${coreDef.name.toLowerCase()}() = default;
|
||||
|
||||
|
@ -72,7 +71,7 @@ uint8_t *${coreDef.name.toLowerCase()}::get_regs_base_ptr() {
|
|||
return reinterpret_cast<uint8_t*>(®);
|
||||
}
|
||||
|
||||
${coreDef.name.toLowerCase()}::phys_addr_t ${coreDef.name.toLowerCase()}::virt2phys(const iss::addr_t &pc) {
|
||||
return phys_addr_t(pc); // change logical address to physical address
|
||||
${coreDef.name.toLowerCase()}::phys_addr_t ${coreDef.name.toLowerCase()}::virt2phys(const iss::addr_t &addr) {
|
||||
return phys_addr_t(addr.access, addr.space, addr.val&traits<${coreDef.name.toLowerCase()}>::addr_mask);
|
||||
}
|
||||
|
||||
// clang-format on
|
||||
|
|
|
@ -30,14 +30,12 @@
|
|||
*
|
||||
*******************************************************************************/
|
||||
<%
|
||||
import com.minres.coredsl.util.BigIntegerWithRadix
|
||||
|
||||
def nativeTypeSize(int size){
|
||||
if(size<=8) return 8; else if(size<=16) return 16; else if(size<=32) return 32; else return 64;
|
||||
}
|
||||
def getRegisterSizes(){
|
||||
def regs = registers.collect{nativeTypeSize(it.size)}
|
||||
regs+=[32,32, 64, 64, 64] // append TRAP_STATE, PENDING_TRAP, ICOUNT, CYCLE, INSTRET
|
||||
regs+=[32,32, 64, 64, 64, 32, 32] // append TRAP_STATE, PENDING_TRAP, ICOUNT, CYCLE, INSTRET, INSTRUCTION, LAST_BRANCH
|
||||
return regs
|
||||
}
|
||||
def getRegisterOffsets(){
|
||||
|
@ -57,15 +55,12 @@ def byteSize(int size){
|
|||
return 128;
|
||||
}
|
||||
def getCString(def val){
|
||||
if(val instanceof BigIntegerWithRadix)
|
||||
return ((BigIntegerWithRadix)val).toCString()
|
||||
else
|
||||
return val.toString()
|
||||
return val.toString()+'ULL'
|
||||
}
|
||||
%>
|
||||
#ifndef _${coreDef.name.toUpperCase()}_H_
|
||||
#define _${coreDef.name.toUpperCase()}_H_
|
||||
|
||||
// clang-format off
|
||||
#include <array>
|
||||
#include <iss/arch/traits.h>
|
||||
#include <iss/arch_if.h>
|
||||
|
@ -81,22 +76,17 @@ 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}.join('", "')}"}};
|
||||
{"${registers.collect{it.name.toLowerCase()}.join('", "')}"}};
|
||||
|
||||
static constexpr std::array<const char*, ${registers.size}> reg_aliases{
|
||||
{"${registers.collect{it.alias}.join('", "')}"}};
|
||||
{"${registers.collect{it.alias.toLowerCase()}.join('", "')}"}};
|
||||
|
||||
enum constants {${constants.collect{c -> c.name+"="+getCString(c.value)}.join(', ')}};
|
||||
|
||||
constexpr static unsigned FP_REGS_SIZE = ${constants.find {it.name=='FLEN'}?.value?:0};
|
||||
|
||||
enum reg_e {
|
||||
${registers.collect{it.name}.join(', ')}, NUM_REGS,
|
||||
TRAP_STATE=NUM_REGS,
|
||||
PENDING_TRAP,
|
||||
ICOUNT,
|
||||
CYCLE,
|
||||
INSTRET
|
||||
${registers.collect{it.name}.join(', ')}, NUM_REGS, TRAP_STATE=NUM_REGS, PENDING_TRAP, ICOUNT, CYCLE, INSTRET, INSTRUCTION, LAST_BRANCH
|
||||
};
|
||||
|
||||
using reg_t = uint${addrDataWidth}_t;
|
||||
|
@ -121,7 +111,7 @@ template <> struct traits<${coreDef.name.toLowerCase()}> {
|
|||
|
||||
enum mem_type_e { ${spaces.collect{it.name}.join(', ')} };
|
||||
|
||||
enum class opcode_e : unsigned short {<%instructions.eachWithIndex{instr, index -> %>
|
||||
enum class opcode_e {<%instructions.eachWithIndex{instr, index -> %>
|
||||
${instr.instruction.name} = ${index},<%}%>
|
||||
MAX_OPCODE
|
||||
};
|
||||
|
@ -147,14 +137,6 @@ struct ${coreDef.name.toLowerCase()}: public arch_if {
|
|||
|
||||
inline uint64_t stop_code() { return interrupt_sim; }
|
||||
|
||||
inline phys_addr_t v2p(const iss::addr_t& addr){
|
||||
if (addr.space != traits<${coreDef.name.toLowerCase()}>::MEM || addr.type == iss::address_type::PHYSICAL ||
|
||||
addr_mode[static_cast<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; }
|
||||
|
@ -169,8 +151,10 @@ struct ${coreDef.name.toLowerCase()}: public arch_if {
|
|||
}}%>
|
||||
uint32_t trap_state = 0, pending_trap = 0;
|
||||
uint64_t icount = 0;
|
||||
uint64_t cycle = 0;
|
||||
uint64_t instret = 0;
|
||||
uint32_t last_branch;
|
||||
uint32_t instruction = 0;
|
||||
uint32_t last_branch = 0;
|
||||
} reg;
|
||||
#pragma pack(pop)
|
||||
std::array<address_type, 4> addr_mode;
|
||||
|
@ -190,3 +174,4 @@ if(fcsr != null) {%>
|
|||
}
|
||||
}
|
||||
#endif /* _${coreDef.name.toUpperCase()}_H_ */
|
||||
// clang-format on
|
||||
|
|
|
@ -8,9 +8,14 @@
|
|||
instrGroups[groupName]+=it;
|
||||
}
|
||||
instrGroups
|
||||
}%><%getInstructionGroups().each{name, instrList -> %>
|
||||
${name}: <% instrList.findAll{!it.instruction.name.startsWith("__")}.each { %>
|
||||
- ${it.instruction.name}:
|
||||
}%><%int index = 0; getInstructionGroups().each{name, instrList -> %>
|
||||
${name}: <% instrList.each { %>
|
||||
${it.instruction.name}:
|
||||
index: ${index++}
|
||||
encoding: ${it.encoding}
|
||||
mask: ${it.mask}<%}}%>
|
||||
mask: ${it.mask}<%if(it.attributes.size) {%>
|
||||
attributes: ${it.attributes}<%}%>
|
||||
size: ${it.length}
|
||||
branch: ${it.modifiesPC}
|
||||
delay: ${it.isConditional?"[1,1]":"1"}<%}}%>
|
||||
|
||||
|
|
|
@ -0,0 +1,131 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (C) 2023 MINRES Technologies GmbH
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*******************************************************************************/
|
||||
// clang-format off
|
||||
#include <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
|
|
@ -0,0 +1,281 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (C) 2017, 2023 MINRES Technologies GmbH
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*******************************************************************************/
|
||||
// clang-format off
|
||||
#include <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 vm_base<ARCH>::get_reg_ptr;
|
||||
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;
|
||||
inline const char *name(size_t index){return traits::reg_aliases.at(index);}
|
||||
|
||||
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);
|
||||
}
|
||||
#include <vm/asmjit/helper_func.h>
|
||||
|
||||
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 */
|
||||
}
|
||||
x86::Compiler& cc = jh.cc;
|
||||
//ideally only do this if necessary (someone / plugin needs it)
|
||||
cc.mov(jh.pc,PC);
|
||||
cc.comment(fmt::format("\\n${instr.name}_{:#x}:",pc.val).c_str());
|
||||
this->gen_sync(jh, PRE_SYNC, ${idx});
|
||||
pc=pc+ ${instr.length/8};
|
||||
|
||||
gen_instr_prologue(jh, pc.val);
|
||||
cc.comment("\\n//behavior:");
|
||||
/*generate behavior*/
|
||||
<%instr.behavior.eachLine{%>${it}
|
||||
<%}%>
|
||||
gen_instr_epilogue(jh);
|
||||
this->gen_sync(jh, POST_SYNC, ${idx});
|
||||
return returnValue;
|
||||
}
|
||||
<%}%>
|
||||
/****************************************************************************
|
||||
* end opcode definitions
|
||||
****************************************************************************/
|
||||
continuation_e illegal_intruction(virt_addr_t &pc, code_word_t instr, jit_holder& jh ) {
|
||||
|
||||
return BRANCH;
|
||||
}
|
||||
//decoding functionality
|
||||
|
||||
void populate_decoding_tree(decoding_tree_node* root){
|
||||
//create submask
|
||||
for(auto instr: root->instrs){
|
||||
root->submask &= instr.mask;
|
||||
}
|
||||
//put each instr according to submask&encoding into children
|
||||
for(auto instr: root->instrs){
|
||||
bool foundMatch = false;
|
||||
for(auto child: root->children){
|
||||
//use value as identifying trait
|
||||
if(child->value == (instr.value&root->submask)){
|
||||
child->instrs.push_back(instr);
|
||||
foundMatch = true;
|
||||
}
|
||||
}
|
||||
if(!foundMatch){
|
||||
decoding_tree_node* child = new decoding_tree_node(instr.value&root->submask);
|
||||
child->instrs.push_back(instr);
|
||||
root->children.push_back(child);
|
||||
}
|
||||
}
|
||||
root->instrs.clear();
|
||||
//call populate_decoding_tree for all children
|
||||
if(root->children.size() >1)
|
||||
for(auto child: root->children){
|
||||
populate_decoding_tree(child);
|
||||
}
|
||||
else{
|
||||
//sort instrs by value of the mask, this works bc we want to have the least restrictive one last
|
||||
std::sort(root->children[0]->instrs.begin(), root->children[0]->instrs.end(), [](const instruction_descriptor& instr1, const instruction_descriptor& instr2) {
|
||||
return instr1.mask > instr2.mask;
|
||||
});
|
||||
}
|
||||
}
|
||||
compile_func decode_instr(decoding_tree_node* node, code_word_t word){
|
||||
if(!node->children.size()){
|
||||
if(node->instrs.size() == 1) return node->instrs[0].op;
|
||||
for(auto instr : node->instrs){
|
||||
if((instr.mask&word) == instr.value) return instr.op;
|
||||
}
|
||||
}
|
||||
else{
|
||||
for(auto child : node->children){
|
||||
if (child->value == (node->submask&word)){
|
||||
return decode_instr(child, word);
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
template <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>
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // 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 asmjit
|
||||
} // namespace iss
|
||||
|
||||
#include <iss/factory.h>
|
||||
#include <iss/arch/riscv_hart_m_p.h>
|
||||
#include <iss/arch/riscv_hart_mu_p.h>
|
||||
namespace iss {
|
||||
namespace {
|
||||
volatile std::array<bool, 2> dummy = {
|
||||
core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|m_p|asmjit", [](unsigned port, void*) -> 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);
|
||||
return {cpu_ptr{cpu}, vm_ptr{vm}};
|
||||
}),
|
||||
core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p|asmjit", [](unsigned port, void*) -> 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);
|
||||
return {cpu_ptr{cpu}, vm_ptr{vm}};
|
||||
})
|
||||
};
|
||||
}
|
||||
}
|
||||
// clang-format on
|
|
@ -30,23 +30,23 @@
|
|||
*
|
||||
*******************************************************************************/
|
||||
<%
|
||||
import com.minres.coredsl.util.BigIntegerWithRadix
|
||||
|
||||
def nativeTypeSize(int size){
|
||||
if(size<=8) return 8; else if(size<=16) return 16; else if(size<=32) return 32; else return 64;
|
||||
}
|
||||
%>
|
||||
#include "../fp_functions.h"
|
||||
// clang-format off
|
||||
#include <iss/arch/${coreDef.name.toLowerCase()}.h>
|
||||
#include <iss/arch/riscv_hart_m_p.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 <sstream>
|
||||
#include <boost/coroutine2/all.hpp>
|
||||
#include <functional>
|
||||
#include <exception>
|
||||
#include <vector>
|
||||
#include <sstream>
|
||||
|
||||
#ifndef FMT_HEADER_ONLY
|
||||
#define FMT_HEADER_ONLY
|
||||
|
@ -63,6 +63,10 @@ using namespace iss::arch;
|
|||
using namespace iss::debugger;
|
||||
using namespace std::placeholders;
|
||||
|
||||
struct memory_access_exception : public std::exception{
|
||||
memory_access_exception(){}
|
||||
};
|
||||
|
||||
template <typename ARCH> class vm_impl : public iss::interp::vm_base<ARCH> {
|
||||
public:
|
||||
using traits = arch::traits<ARCH>;
|
||||
|
@ -73,6 +77,7 @@ public:
|
|||
using addr_t = typename super::addr_t;
|
||||
using reg_t = typename traits::reg_t;
|
||||
using mem_type_e = typename traits::mem_type_e;
|
||||
using opcode_e = typename traits::opcode_e;
|
||||
|
||||
vm_impl();
|
||||
|
||||
|
@ -92,37 +97,16 @@ protected:
|
|||
using compile_ret_t = virt_addr_t;
|
||||
using compile_func = compile_ret_t (this_class::*)(virt_addr_t &pc, code_word_t instr);
|
||||
|
||||
inline const char *name(size_t index){return traits::reg_aliases.at(index);}
|
||||
inline const char *name(size_t index){return index<traits::reg_aliases.size()?traits::reg_aliases[index]:"illegal";}
|
||||
|
||||
typename arch::traits<ARCH>::opcode_e decode_inst_id(code_word_t instr);
|
||||
virt_addr_t execute_inst(finish_cond_e cond, virt_addr_t start, uint64_t icount_limit) override;
|
||||
|
||||
// some compile time constants
|
||||
// enum { MASK16 = 0b1111110001100011, MASK32 = 0b11111111111100000111000001111111 };
|
||||
enum { MASK16 = 0b1111111111111111, MASK32 = 0b11111111111100000111000001111111 };
|
||||
enum { EXTR_MASK16 = MASK16 >> 2, EXTR_MASK32 = MASK32 >> 2 };
|
||||
enum {
|
||||
LUT_SIZE = 1 << util::bit_count(static_cast<uint32_t>(EXTR_MASK32)),
|
||||
LUT_SIZE_C = 1 << util::bit_count(static_cast<uint32_t>(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;
|
||||
|
||||
struct instruction_pattern {
|
||||
uint32_t value;
|
||||
uint32_t mask;
|
||||
typename arch::traits<ARCH>::opcode_e id;
|
||||
};
|
||||
|
||||
std::array<std::vector<instruction_pattern>, 4> qlut;
|
||||
|
||||
inline void raise(uint16_t trap_id, uint16_t cause){
|
||||
auto trap_val = 0x80ULL << 24 | (cause << 16) | trap_id;
|
||||
this->template get_reg<uint32_t>(traits::TRAP_STATE) = trap_val;
|
||||
this->template get_reg<uint32_t>(traits::NEXT_PC) = std::numeric_limits<uint32_t>::max();
|
||||
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){
|
||||
|
@ -137,44 +121,6 @@ protected:
|
|||
using coro_t = boost::coroutines2::coroutine<void>::pull_type;
|
||||
std::vector<coro_t> spawn_blocks;
|
||||
|
||||
template<typename T>
|
||||
T& pc_assign(T& val){super::ex_info.branch_taken=true; return val;}
|
||||
inline uint8_t readSpace1(typename super::mem_type_e space, uint64_t addr){
|
||||
auto ret = super::template read_mem<uint8_t>(space, addr);
|
||||
if(this->template get_reg<uint32_t>(traits::TRAP_STATE)) throw 0;
|
||||
return ret;
|
||||
}
|
||||
inline uint16_t readSpace2(typename super::mem_type_e space, uint64_t addr){
|
||||
auto ret = super::template read_mem<uint16_t>(space, addr);
|
||||
if(this->template get_reg<uint32_t>(traits::TRAP_STATE)) throw 0;
|
||||
return ret;
|
||||
}
|
||||
inline uint32_t readSpace4(typename super::mem_type_e space, uint64_t addr){
|
||||
auto ret = super::template read_mem<uint32_t>(space, addr);
|
||||
if(this->template get_reg<uint32_t>(traits::TRAP_STATE)) throw 0;
|
||||
return ret;
|
||||
}
|
||||
inline uint64_t readSpace8(typename super::mem_type_e space, uint64_t addr){
|
||||
auto ret = super::template read_mem<uint64_t>(space, addr);
|
||||
if(this->template get_reg<uint32_t>(traits::TRAP_STATE)) throw 0;
|
||||
return ret;
|
||||
}
|
||||
inline void writeSpace1(typename super::mem_type_e space, uint64_t addr, uint8_t data){
|
||||
super::write_mem(space, addr, data);
|
||||
if(this->template get_reg<uint32_t>(traits::TRAP_STATE)) throw 0;
|
||||
}
|
||||
inline void writeSpace2(typename super::mem_type_e space, uint64_t addr, uint16_t data){
|
||||
super::write_mem(space, addr, data);
|
||||
if(this->template get_reg<uint32_t>(traits::TRAP_STATE)) throw 0;
|
||||
}
|
||||
inline void writeSpace4(typename super::mem_type_e space, uint64_t addr, uint32_t data){
|
||||
super::write_mem(space, addr, data);
|
||||
if(this->template get_reg<uint32_t>(traits::TRAP_STATE)) throw 0;
|
||||
}
|
||||
inline void writeSpace8(typename super::mem_type_e space, uint64_t addr, uint64_t data){
|
||||
super::write_mem(space, addr, data);
|
||||
if(this->template get_reg<uint32_t>(traits::TRAP_STATE)) throw 0;
|
||||
}
|
||||
template<unsigned W, typename U, typename S = typename std::make_signed<U>::type>
|
||||
inline S sext(U from) {
|
||||
auto mask = (1ULL<<W) - 1;
|
||||
|
@ -183,6 +129,7 @@ protected:
|
|||
}
|
||||
|
||||
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)();
|
||||
|
@ -193,34 +140,101 @@ protected:
|
|||
<%functions.each{ it.eachLine { %>
|
||||
${it}<%}%>
|
||||
<%}%>
|
||||
|
||||
private:
|
||||
/****************************************************************************
|
||||
* start opcode definitions
|
||||
****************************************************************************/
|
||||
struct InstructionDesriptor {
|
||||
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){}
|
||||
};
|
||||
|
||||
const std::array<InstructionDesriptor, ${instructions.size}> instr_descr = {{
|
||||
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}},<%}%>
|
||||
}};
|
||||
|
||||
//static constexpr typename traits::addr_t upper_bits = ~traits::PGMASK;
|
||||
iss::status fetch_ins(virt_addr_t pc, uint8_t * data){
|
||||
auto phys_pc = this->core.v2p(pc);
|
||||
if(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;
|
||||
// if (this->core.read(this->core.v2p(pc + 2), 2, data + 2) != iss::Ok)
|
||||
// return iss::Err;
|
||||
// } else {
|
||||
if (this->core.read(phys_pc, 4, data) != iss::Ok) return iss::Err;
|
||||
if (this->core.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) {
|
||||
|
@ -247,16 +261,11 @@ constexpr size_t bit_count(uint32_t u) {
|
|||
template <typename ARCH>
|
||||
vm_impl<ARCH>::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id)
|
||||
: vm_base<ARCH>(core, core_id, cluster_id) {
|
||||
unsigned id=0;
|
||||
root = new decoding_tree_node(std::numeric_limits<uint32_t>::max());
|
||||
for(auto instr:instr_descr){
|
||||
auto quadrant = instr.value & 0x3;
|
||||
qlut[quadrant].push_back(instruction_pattern{instr.value, instr.mask, instr.op});
|
||||
}
|
||||
for(auto& lut: qlut){
|
||||
std::sort(std::begin(lut), std::end(lut), [](instruction_pattern const& a, instruction_pattern const& b){
|
||||
return bit_count(a.mask) > bit_count(b.mask);
|
||||
});
|
||||
root->instrs.push_back(instr);
|
||||
}
|
||||
populate_decoding_tree(root);
|
||||
}
|
||||
|
||||
inline bool is_count_limit_enabled(finish_cond_e cond){
|
||||
|
@ -267,45 +276,38 @@ 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 arch::traits<ARCH>::opcode_e vm_impl<ARCH>::decode_inst_id(code_word_t instr){
|
||||
for(auto& e: qlut[instr&0x3]){
|
||||
if(!((instr&e.mask) ^ e.value )) return e.id;
|
||||
}
|
||||
return arch::traits<ARCH>::opcode_e::MAX_OPCODE;
|
||||
}
|
||||
|
||||
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){
|
||||
// we fetch at max 4 byte, alignment is 2
|
||||
code_word_t instr = 0;
|
||||
auto *const data = (uint8_t *)&instr;
|
||||
auto pc=start;
|
||||
|
||||
auto* PC = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::PC]);
|
||||
auto* NEXT_PC = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::NEXT_PC]);
|
||||
auto* trap_state = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::TRAP_STATE]);
|
||||
auto* icount = reinterpret_cast<uint64_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::ICOUNT]);
|
||||
auto* instret = reinterpret_cast<uint64_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::INSTRET]);
|
||||
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) && this->core.get_icount() >= icount_limit)){
|
||||
!(is_count_limit_enabled(cond) && icount >= icount_limit)){
|
||||
if(fetch_ins(pc, data)!=iss::Ok){
|
||||
this->do_sync(POST_SYNC, std::numeric_limits<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_inst_id(instr);
|
||||
auto inst_id = decode_instr(root, instr);
|
||||
// pre execution stuff
|
||||
this->core.reg.last_branch = 0;
|
||||
if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, static_cast<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}
|
||||
<%}%>
|
||||
/* generate console output when executing the command */<%instr.disass.eachLine{%>
|
||||
${it}<%}%>
|
||||
}
|
||||
// used registers<%instr.usedVariables.each{ k,v->
|
||||
if(v.isArray) {%>
|
||||
|
@ -313,28 +315,29 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
|||
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
|
||||
try {
|
||||
<%instr.behavior.eachLine{%>${it}
|
||||
<%}%>} catch(...){}
|
||||
}
|
||||
break;<%}%>
|
||||
// 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);
|
||||
if(trap_state!=0){
|
||||
super::core.enter_trap(trap_state, pc.val, instr);
|
||||
} else {
|
||||
(*icount)++;
|
||||
(*instret)++;
|
||||
icount++;
|
||||
instret++;
|
||||
}
|
||||
(*reinterpret_cast<uint64_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::CYCLE]))++;
|
||||
cycle++;
|
||||
pc.val=*NEXT_PC;
|
||||
this->core.reg.PC = this->core.reg.NEXT_PC;
|
||||
this->core.reg.trap_state = this->core.reg.pending_trap;
|
||||
|
@ -343,7 +346,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
|||
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) {
|
||||
|
@ -353,3 +356,26 @@ std::unique_ptr<vm_if> create<arch::${coreDef.name.toLowerCase()}>(arch::${coreD
|
|||
}
|
||||
} // namespace interp
|
||||
} // namespace iss
|
||||
|
||||
#include <iss/factory.h>
|
||||
#include <iss/arch/riscv_hart_m_p.h>
|
||||
#include <iss/arch/riscv_hart_mu_p.h>
|
||||
namespace iss {
|
||||
namespace {
|
||||
volatile std::array<bool, 2> dummy = {
|
||||
core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|m_p|interp", [](unsigned port, void*) -> 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);
|
||||
return {cpu_ptr{cpu}, vm_ptr{vm}};
|
||||
}),
|
||||
core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p|interp", [](unsigned port, void*) -> 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);
|
||||
return {cpu_ptr{cpu}, vm_ptr{vm}};
|
||||
})
|
||||
};
|
||||
}
|
||||
}
|
||||
// clang-format on
|
|
@ -29,9 +29,8 @@
|
|||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
// clang-format off
|
||||
#include <iss/arch/${coreDef.name.toLowerCase()}.h>
|
||||
#include <iss/arch/riscv_hart_m_p.h>
|
||||
#include <iss/debugger/gdb_session.h>
|
||||
#include <iss/debugger/server.h>
|
||||
#include <iss/iss.h>
|
||||
|
@ -59,6 +58,7 @@ 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;
|
||||
|
@ -81,7 +81,7 @@ public:
|
|||
protected:
|
||||
using vm_base<ARCH>::get_reg_ptr;
|
||||
|
||||
inline const char *name(size_t index){return traits<ARCH>::reg_aliases.at(index);}
|
||||
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()));
|
||||
|
@ -89,7 +89,7 @@ protected:
|
|||
|
||||
void setup_module(Module* m) override {
|
||||
super::setup_module(m);
|
||||
iss::llvm::fp_impl::add_fp_functions_2_module(m, traits<ARCH>::FP_REGS_SIZE, traits<ARCH>::XLEN);
|
||||
iss::llvm::fp_impl::add_fp_functions_2_module(m, traits::FP_REGS_SIZE, traits::XLEN);
|
||||
}
|
||||
|
||||
inline Value *gen_choose(Value *cond, Value *trueVal, Value *falseVal, unsigned size) {
|
||||
|
@ -111,116 +111,150 @@ protected:
|
|||
void gen_trap_check(BasicBlock *bb);
|
||||
|
||||
inline Value *gen_reg_load(unsigned i, unsigned level = 0) {
|
||||
return this->builder.CreateLoad(get_reg_ptr(i), false);
|
||||
return this->builder.CreateLoad(this->get_typeptr(i), get_reg_ptr(i), false);
|
||||
}
|
||||
|
||||
inline void gen_set_pc(virt_addr_t pc, unsigned reg_num) {
|
||||
Value *next_pc_v = this->builder.CreateSExtOrTrunc(this->gen_const(traits<ARCH>::XLEN, pc.val),
|
||||
this->get_type(traits<ARCH>::XLEN));
|
||||
Value *next_pc_v = this->builder.CreateSExtOrTrunc(this->gen_const(traits::XLEN, pc.val),
|
||||
this->get_type(traits::XLEN));
|
||||
this->builder.CreateStore(next_pc_v, get_reg_ptr(reg_num), true);
|
||||
}
|
||||
|
||||
// some compile time constants
|
||||
// enum { MASK16 = 0b1111110001100011, MASK32 = 0b11111111111100000111000001111111 };
|
||||
enum { MASK16 = 0b1111111111111111, MASK32 = 0b11111111111100000111000001111111 };
|
||||
enum { EXTR_MASK16 = MASK16 >> 2, EXTR_MASK32 = MASK32 >> 2 };
|
||||
enum { LUT_SIZE = 1 << util::bit_count(EXTR_MASK32), LUT_SIZE_C = 1 << util::bit_count(EXTR_MASK16) };
|
||||
|
||||
using this_class = vm_impl<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;
|
||||
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 InstructionDesriptor {
|
||||
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){}
|
||||
};
|
||||
|
||||
const std::array<InstructionDesriptor, ${instructions.size}> instr_descr = {{
|
||||
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} */
|
||||
{${instr.length}, ${instr.value}, ${instr.mask}, &this_class::__${generator.functionName(instr.name)}},<%}%>
|
||||
/* instruction ${instr.instruction.name}, encoding '${instr.encoding}' */
|
||||
{${instr.length}, ${instr.encoding}, ${instr.mask}, &this_class::__${generator.functionName(instr.name)}},<%}%>
|
||||
}};
|
||||
|
||||
/* instruction definitions */<%instructions.eachWithIndex{instr, idx -> %>
|
||||
/* instruction ${idx}: ${instr.name} */
|
||||
std::tuple<continuation_e, BasicBlock*> __${generator.functionName(instr.name)}(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){<%instr.code.eachLine{%>
|
||||
std::tuple<continuation_e, BasicBlock*> __${generator.functionName(instr.name)}(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){
|
||||
bb->setName(fmt::format("${instr.name}_0x{:X}",pc.val));
|
||||
this->gen_sync(PRE_SYNC,${idx});
|
||||
uint64_t PC = pc.val;
|
||||
<%instr.fields.eachLine{%>${it}
|
||||
<%}%>if(this->disass_enabled){
|
||||
/* generate console output when executing the command */<%instr.disass.eachLine{%>
|
||||
${it}<%}%>
|
||||
}
|
||||
auto cur_pc_val = this->gen_const(32,pc.val);
|
||||
pc=pc+ ${instr.length/8};
|
||||
this->gen_set_pc(pc, traits::NEXT_PC);
|
||||
<%instr.behavior.eachLine{%>${it}
|
||||
<%}%>
|
||||
this->gen_trap_check(bb);
|
||||
this->gen_sync(POST_SYNC, ${idx});
|
||||
this->builder.CreateBr(bb);
|
||||
return returnValue;
|
||||
}
|
||||
<%}%>
|
||||
/****************************************************************************
|
||||
* 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.CreateLoad(this->get_typeptr(traits::NEXT_PC), get_reg_ptr(traits::NEXT_PC), true),
|
||||
get_reg_ptr(traits::PC), true);
|
||||
this->builder.CreateStore(
|
||||
this->builder.CreateAdd(this->builder.CreateLoad(get_reg_ptr(traits<ARCH>::ICOUNT), true),
|
||||
this->builder.CreateAdd(this->builder.CreateLoad(this->get_typeptr(traits::ICOUNT), get_reg_ptr(traits::ICOUNT), true),
|
||||
this->gen_const(64U, 1)),
|
||||
get_reg_ptr(traits<ARCH>::ICOUNT), true);
|
||||
get_reg_ptr(traits::ICOUNT), true);
|
||||
pc = pc + ((instr & 3) == 3 ? 4 : 2);
|
||||
this->gen_raise_trap(0, 2); // illegal instruction trap
|
||||
this->gen_sync(iss::POST_SYNC, instr_descr.size());
|
||||
this->gen_trap_check(this->leave_blk);
|
||||
return std::make_tuple(BRANCH, nullptr);
|
||||
}
|
||||
//decoding functionality
|
||||
|
||||
void populate_decoding_tree(decoding_tree_node* root){
|
||||
//create submask
|
||||
for(auto instr: root->instrs){
|
||||
root->submask &= instr.mask;
|
||||
}
|
||||
//put each instr according to submask&encoding into children
|
||||
for(auto instr: root->instrs){
|
||||
bool foundMatch = false;
|
||||
for(auto child: root->children){
|
||||
//use value as identifying trait
|
||||
if(child->value == (instr.value&root->submask)){
|
||||
child->instrs.push_back(instr);
|
||||
foundMatch = true;
|
||||
}
|
||||
}
|
||||
if(!foundMatch){
|
||||
decoding_tree_node* child = new decoding_tree_node(instr.value&root->submask);
|
||||
child->instrs.push_back(instr);
|
||||
root->children.push_back(child);
|
||||
}
|
||||
}
|
||||
root->instrs.clear();
|
||||
//call populate_decoding_tree for all children
|
||||
if(root->children.size() >1)
|
||||
for(auto child: root->children){
|
||||
populate_decoding_tree(child);
|
||||
}
|
||||
else{
|
||||
//sort instrs by value of the mask, this works bc we want to have the least restrictive one last
|
||||
std::sort(root->children[0]->instrs.begin(), root->children[0]->instrs.end(), [](const instruction_descriptor& instr1, const instruction_descriptor& instr2) {
|
||||
return instr1.mask > instr2.mask;
|
||||
});
|
||||
}
|
||||
}
|
||||
compile_func decode_instr(decoding_tree_node* node, code_word_t word){
|
||||
if(!node->children.size()){
|
||||
if(node->instrs.size() == 1) return node->instrs[0].op;
|
||||
for(auto instr : node->instrs){
|
||||
if((instr.mask&word) == instr.value) return instr.op;
|
||||
}
|
||||
}
|
||||
else{
|
||||
for(auto child : node->children){
|
||||
if (child->value == (node->submask&word)){
|
||||
return decode_instr(child, word);
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename CODE_WORD> void debug_fn(CODE_WORD insn) {
|
||||
volatile CODE_WORD x = insn;
|
||||
insn = 2 * x;
|
||||
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()); }
|
||||
|
@ -228,14 +262,11 @@ 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();
|
||||
root = new decoding_tree_node(std::numeric_limits<uint32_t>::max());
|
||||
for(auto instr:instr_descr){
|
||||
auto quantrant = instr.value & 0x3;
|
||||
expand_bit_mask(29, lutmasks[quantrant], instr.value >> 2, instr.mask >> 2, 0, qlut[quantrant], instr.op);
|
||||
root->instrs.push_back(instr);
|
||||
}
|
||||
populate_decoding_tree(root);
|
||||
}
|
||||
|
||||
template <typename ARCH>
|
||||
|
@ -243,49 +274,50 @@ 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;
|
||||
code_word_t instr = 0;
|
||||
// const typename traits::addr_t upper_bits = ~traits::PGMASK;
|
||||
phys_addr_t paddr(pc);
|
||||
auto *const data = (uint8_t *)&insn;
|
||||
paddr = this->core.v2p(pc);
|
||||
if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary
|
||||
auto res = this->core.read(paddr, 2, data);
|
||||
if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val);
|
||||
if ((insn & 0x3) == 0x3) { // this is a 32bit instruction
|
||||
res = this->core.read(this->core.v2p(pc + 2), 2, data + 2);
|
||||
}
|
||||
} else {
|
||||
auto *const data = (uint8_t *)&instr;
|
||||
if(this->core.has_mmu())
|
||||
paddr = this->core.virt2phys(pc);
|
||||
//TODO: re-add page handling
|
||||
// if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary
|
||||
// auto res = this->core.read(paddr, 2, data);
|
||||
// if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val);
|
||||
// if ((instr & 0x3) == 0x3) { // this is a 32bit instruction
|
||||
// res = this->core.read(this->core.v2p(pc + 2), 2, data + 2);
|
||||
// }
|
||||
// } else {
|
||||
auto res = this->core.read(paddr, 4, data);
|
||||
if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val);
|
||||
}
|
||||
if (insn == 0x0000006f || (insn&0xffff)==0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0'
|
||||
// }
|
||||
if (instr == 0x0000006f || (instr&0xffff)==0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0'
|
||||
// curr pc on stack
|
||||
++inst_cnt;
|
||||
auto lut_val = extract_fields(insn);
|
||||
auto f = qlut[insn & 0x3][lut_val];
|
||||
auto f = decode_instr(root, instr);
|
||||
if (f == nullptr) {
|
||||
f = &this_class::illegal_intruction;
|
||||
}
|
||||
return (this->*f)(pc, insn, this_block);
|
||||
return (this->*f)(pc, instr, this_block);
|
||||
}
|
||||
|
||||
template <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));
|
||||
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<ARCH>::TRAP_STATE), true);
|
||||
this->builder.CreateStore(this->gen_const(32U, std::numeric_limits<uint32_t>::max()), get_reg_ptr(traits<ARCH>::LAST_BRANCH), false);
|
||||
this->builder.CreateStore(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<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);
|
||||
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) {
|
||||
|
@ -295,22 +327,25 @@ template <typename ARCH> void vm_impl<ARCH>::gen_wait(unsigned type) {
|
|||
|
||||
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->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<ARCH>::LAST_BRANCH), false);
|
||||
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(get_reg_ptr(traits<ARCH>::PC), false))};
|
||||
this->adj_to64(this->builder.CreateLoad(this->get_typeptr(traits::PC), get_reg_ptr(traits::PC), false))};
|
||||
this->builder.CreateCall(this->mod->getFunction("enter_trap"), args);
|
||||
auto *trap_addr_val = this->builder.CreateLoad(get_reg_ptr(traits<ARCH>::NEXT_PC), false);
|
||||
auto *trap_addr_val = this->builder.CreateLoad(this->get_typeptr(traits::NEXT_PC), get_reg_ptr(traits::NEXT_PC), false);
|
||||
this->builder.CreateRet(trap_addr_val);
|
||||
}
|
||||
|
||||
template <typename ARCH> inline void vm_impl<ARCH>::gen_trap_check(BasicBlock *bb) {
|
||||
auto *v = this->builder.CreateLoad(get_reg_ptr(arch::traits<ARCH>::TRAP_STATE), true);
|
||||
auto* target_bb = BasicBlock::Create(this->mod->getContext(), "", this->func, bb);
|
||||
auto *v = this->builder.CreateLoad(this->get_typeptr(traits::TRAP_STATE), get_reg_ptr(traits::TRAP_STATE), true);
|
||||
this->gen_cond_branch(this->builder.CreateICmp(
|
||||
ICmpInst::ICMP_EQ, v,
|
||||
ConstantInt::get(getContext(), APInt(v->getType()->getIntegerBitWidth(), 0))),
|
||||
bb, this->trap_blk, 1);
|
||||
target_bb, this->trap_blk, 1);
|
||||
this->builder.SetInsertPoint(target_bb);
|
||||
}
|
||||
|
||||
} // namespace ${coreDef.name.toLowerCase()}
|
||||
|
@ -323,3 +358,26 @@ std::unique_ptr<vm_if> create<arch::${coreDef.name.toLowerCase()}>(arch::${coreD
|
|||
}
|
||||
} // namespace llvm
|
||||
} // namespace iss
|
||||
|
||||
#include <iss/factory.h>
|
||||
#include <iss/arch/riscv_hart_m_p.h>
|
||||
#include <iss/arch/riscv_hart_mu_p.h>
|
||||
namespace iss {
|
||||
namespace {
|
||||
volatile std::array<bool, 2> dummy = {
|
||||
core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|m_p|llvm", [](unsigned port, void*) -> 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);
|
||||
return {cpu_ptr{cpu}, vm_ptr{vm}};
|
||||
}),
|
||||
core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p|llvm", [](unsigned port, void*) -> 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);
|
||||
return {cpu_ptr{cpu}, vm_ptr{vm}};
|
||||
})
|
||||
};
|
||||
}
|
||||
}
|
||||
// clang-format on
|
|
@ -1,9 +0,0 @@
|
|||
{
|
||||
"${coreDef.name}" : [<%instructions.eachWithIndex{instr,index -> %>${index==0?"":","}
|
||||
{
|
||||
"name" : "${instr.name}",
|
||||
"size" : ${instr.length},
|
||||
"delay" : ${generator.hasAttribute(instr.instruction, com.minres.coredsl.coreDsl.InstrAttribute.COND)?[1,1]:1}
|
||||
}<%}%>
|
||||
]
|
||||
}
|
|
@ -1,223 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (C) 2017, 2018 MINRES Technologies GmbH
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
<%
|
||||
import com.minres.coredsl.coreDsl.Register
|
||||
import com.minres.coredsl.coreDsl.RegisterFile
|
||||
import com.minres.coredsl.coreDsl.RegisterAlias
|
||||
def getTypeSize(size){
|
||||
if(size > 32) 64 else if(size > 16) 32 else if(size > 8) 16 else 8
|
||||
}
|
||||
def getOriginalName(reg){
|
||||
if( reg.original instanceof RegisterFile) {
|
||||
if( reg.index != null ) {
|
||||
return reg.original.name+generator.generateHostCode(reg.index)
|
||||
} else {
|
||||
return reg.original.name
|
||||
}
|
||||
} else if(reg.original instanceof Register){
|
||||
return reg.original.name
|
||||
}
|
||||
}
|
||||
def getRegisterNames(){
|
||||
def regNames = []
|
||||
allRegs.each { reg ->
|
||||
if( reg instanceof RegisterFile) {
|
||||
(reg.range.right..reg.range.left).each{
|
||||
regNames+=reg.name.toLowerCase()+it
|
||||
}
|
||||
} else if(reg instanceof Register){
|
||||
regNames+=reg.name.toLowerCase()
|
||||
}
|
||||
}
|
||||
return regNames
|
||||
}
|
||||
def getRegisterAliasNames(){
|
||||
def regMap = allRegs.findAll{it instanceof RegisterAlias }.collectEntries {[getOriginalName(it), it.name]}
|
||||
return allRegs.findAll{it instanceof Register || it instanceof RegisterFile}.collect{reg ->
|
||||
if( reg instanceof RegisterFile) {
|
||||
return (reg.range.right..reg.range.left).collect{ (regMap[reg.name]?:regMap[reg.name+it]?:reg.name.toLowerCase()+it).toLowerCase() }
|
||||
} else if(reg instanceof Register){
|
||||
regMap[reg.name]?:reg.name.toLowerCase()
|
||||
}
|
||||
}.flatten()
|
||||
}
|
||||
%>
|
||||
#ifndef _${coreDef.name.toUpperCase()}_H_
|
||||
#define _${coreDef.name.toUpperCase()}_H_
|
||||
|
||||
#include <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_ */
|
|
@ -1,107 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (C) 2017, 2018 MINRES Technologies GmbH
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*******************************************************************************/
|
||||
<%
|
||||
import com.minres.coredsl.coreDsl.Register
|
||||
import com.minres.coredsl.coreDsl.RegisterFile
|
||||
import com.minres.coredsl.coreDsl.RegisterAlias
|
||||
def getOriginalName(reg){
|
||||
if( reg.original instanceof RegisterFile) {
|
||||
if( reg.index != null ) {
|
||||
return reg.original.name+generator.generateHostCode(reg.index)
|
||||
} else {
|
||||
return reg.original.name
|
||||
}
|
||||
} else if(reg.original instanceof Register){
|
||||
return reg.original.name
|
||||
}
|
||||
}
|
||||
def getRegisterNames(){
|
||||
def regNames = []
|
||||
allRegs.each { reg ->
|
||||
if( reg instanceof RegisterFile) {
|
||||
(reg.range.right..reg.range.left).each{
|
||||
regNames+=reg.name.toLowerCase()+it
|
||||
}
|
||||
} else if(reg instanceof Register){
|
||||
regNames+=reg.name.toLowerCase()
|
||||
}
|
||||
}
|
||||
return regNames
|
||||
}
|
||||
def getRegisterAliasNames(){
|
||||
def regMap = allRegs.findAll{it instanceof RegisterAlias }.collectEntries {[getOriginalName(it), it.name]}
|
||||
return allRegs.findAll{it instanceof Register || it instanceof RegisterFile}.collect{reg ->
|
||||
if( reg instanceof RegisterFile) {
|
||||
return (reg.range.right..reg.range.left).collect{ (regMap[reg.name]?:regMap[reg.name+it]?:reg.name.toLowerCase()+it).toLowerCase() }
|
||||
} else if(reg instanceof Register){
|
||||
regMap[reg.name]?:reg.name.toLowerCase()
|
||||
}
|
||||
}.flatten()
|
||||
}
|
||||
%>
|
||||
#include "util/ities.h"
|
||||
#include <util/logging.h>
|
||||
#include <iss/arch/${coreDef.name.toLowerCase()}.h>
|
||||
#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*>(®);
|
||||
}
|
||||
|
||||
${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
|
||||
}
|
||||
|
|
@ -29,9 +29,8 @@
|
|||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
// clang-format off
|
||||
#include <iss/arch/${coreDef.name.toLowerCase()}.h>
|
||||
#include <iss/arch/riscv_hart_m_p.h>
|
||||
#include <iss/debugger/gdb_session.h>
|
||||
#include <iss/debugger/server.h>
|
||||
#include <iss/iss.h>
|
||||
|
@ -55,10 +54,12 @@ 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;
|
||||
|
||||
|
@ -82,7 +83,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<ARCH>::reg_aliases.at(index);}
|
||||
inline const char *name(size_t index){return traits::reg_aliases.at(index);}
|
||||
|
||||
void setup_module(std::string m) override {
|
||||
super::setup_module(m);
|
||||
|
@ -104,10 +105,10 @@ protected:
|
|||
|
||||
inline void gen_set_pc(tu_builder& tu, virt_addr_t pc, unsigned reg_num) {
|
||||
switch(reg_num){
|
||||
case traits<ARCH>::NEXT_PC:
|
||||
case traits::NEXT_PC:
|
||||
tu("*next_pc = {:#x};", pc.val);
|
||||
break;
|
||||
case traits<ARCH>::PC:
|
||||
case traits::PC:
|
||||
tu("*pc = {:#x};", pc.val);
|
||||
break;
|
||||
default:
|
||||
|
@ -119,80 +120,62 @@ protected:
|
|||
}
|
||||
}
|
||||
|
||||
// some compile time constants
|
||||
// enum { MASK16 = 0b1111110001100011, MASK32 = 0b11111111111100000111000001111111 };
|
||||
enum { MASK16 = 0b1111111111111111, MASK32 = 0b11111111111100000111000001111111 };
|
||||
enum { EXTR_MASK16 = MASK16 >> 2, EXTR_MASK32 = MASK32 >> 2 };
|
||||
enum { LUT_SIZE = 1 << util::bit_count(EXTR_MASK32), LUT_SIZE_C = 1 << util::bit_count(EXTR_MASK16) };
|
||||
|
||||
std::array<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;
|
||||
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 InstructionDesriptor {
|
||||
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){}
|
||||
};
|
||||
|
||||
const std::array<InstructionDesriptor, ${instructions.size}> instr_descr = {{
|
||||
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}, 0b${instr.value}, 0b${instr.mask}, &this_class::__${generator.functionName(instr.name)}},<%}%>
|
||||
{${instr.length}, ${instr.encoding}, ${instr.mask}, &this_class::__${generator.functionName(instr.name)}},<%}%>
|
||||
}};
|
||||
|
||||
/* instruction definitions */<%instructions.eachWithIndex{instr, idx -> %>
|
||||
/* instruction ${idx}: ${instr.name} */
|
||||
compile_ret_t __${generator.functionName(instr.name)}(virt_addr_t& pc, code_word_t instr, tu_builder& tu){<%instr.code.eachLine{%>
|
||||
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{%>
|
||||
${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
|
||||
|
@ -205,11 +188,64 @@ private:
|
|||
vm_impl::gen_trap_check(tu);
|
||||
return BRANCH;
|
||||
}
|
||||
|
||||
//decoding functionality
|
||||
|
||||
void populate_decoding_tree(decoding_tree_node* root){
|
||||
//create submask
|
||||
for(auto instr: root->instrs){
|
||||
root->submask &= instr.mask;
|
||||
}
|
||||
//put each instr according to submask&encoding into children
|
||||
for(auto instr: root->instrs){
|
||||
bool foundMatch = false;
|
||||
for(auto child: root->children){
|
||||
//use value as identifying trait
|
||||
if(child->value == (instr.value&root->submask)){
|
||||
child->instrs.push_back(instr);
|
||||
foundMatch = true;
|
||||
}
|
||||
}
|
||||
if(!foundMatch){
|
||||
decoding_tree_node* child = new decoding_tree_node(instr.value&root->submask);
|
||||
child->instrs.push_back(instr);
|
||||
root->children.push_back(child);
|
||||
}
|
||||
}
|
||||
root->instrs.clear();
|
||||
//call populate_decoding_tree for all children
|
||||
if(root->children.size() >1)
|
||||
for(auto child: root->children){
|
||||
populate_decoding_tree(child);
|
||||
}
|
||||
else{
|
||||
//sort instrs by value of the mask, this works bc we want to have the least restrictive one last
|
||||
std::sort(root->children[0]->instrs.begin(), root->children[0]->instrs.end(), [](const instruction_descriptor& instr1, const instruction_descriptor& instr2) {
|
||||
return instr1.mask > instr2.mask;
|
||||
});
|
||||
}
|
||||
}
|
||||
compile_func decode_instr(decoding_tree_node* node, code_word_t word){
|
||||
if(!node->children.size()){
|
||||
if(node->instrs.size() == 1) return node->instrs[0].op;
|
||||
for(auto instr : node->instrs){
|
||||
if((instr.mask&word) == instr.value) return instr.op;
|
||||
}
|
||||
}
|
||||
else{
|
||||
for(auto child : node->children){
|
||||
if (child->value == (node->submask&word)){
|
||||
return decode_instr(child, word);
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename CODE_WORD> void debug_fn(CODE_WORD insn) {
|
||||
volatile CODE_WORD x = insn;
|
||||
insn = 2 * x;
|
||||
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()); }
|
||||
|
@ -217,14 +253,11 @@ 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();
|
||||
root = new decoding_tree_node(std::numeric_limits<uint32_t>::max());
|
||||
for(auto instr:instr_descr){
|
||||
auto quantrant = instr.value & 0x3;
|
||||
expand_bit_mask(29, lutmasks[quantrant], instr.value >> 2, instr.mask >> 2, 0, qlut[quantrant], instr.op);
|
||||
root->instrs.push_back(instr);
|
||||
}
|
||||
populate_decoding_tree(root);
|
||||
}
|
||||
|
||||
template <typename ARCH>
|
||||
|
@ -232,41 +265,40 @@ 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 insn = 0;
|
||||
const typename traits<ARCH>::addr_t upper_bits = ~traits<ARCH>::PGMASK;
|
||||
code_word_t instr = 0;
|
||||
phys_addr_t paddr(pc);
|
||||
auto *const data = (uint8_t *)&insn;
|
||||
paddr = this->core.v2p(pc);
|
||||
if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary
|
||||
auto res = this->core.read(paddr, 2, data);
|
||||
if(this->core.has_mmu())
|
||||
paddr = this->core.virt2phys(pc);
|
||||
//TODO: re-add page handling
|
||||
// if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary
|
||||
// auto res = this->core.read(paddr, 2, data);
|
||||
// if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val);
|
||||
// if ((insn & 0x3) == 0x3) { // this is a 32bit instruction
|
||||
// res = this->core.read(this->core.v2p(pc + 2), 2, data + 2);
|
||||
// }
|
||||
// } else {
|
||||
auto res = this->core.read(paddr, 4, reinterpret_cast<uint8_t*>(&instr));
|
||||
if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val);
|
||||
if ((insn & 0x3) == 0x3) { // this is a 32bit instruction
|
||||
res = this->core.read(this->core.v2p(pc + 2), 2, data + 2);
|
||||
}
|
||||
} else {
|
||||
auto res = this->core.read(paddr, 4, data);
|
||||
if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val);
|
||||
}
|
||||
if (insn == 0x0000006f || (insn&0xffff)==0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0'
|
||||
// }
|
||||
if (instr == 0x0000006f || (instr&0xffff)==0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0'
|
||||
// curr pc on stack
|
||||
++inst_cnt;
|
||||
auto lut_val = extract_fields(insn);
|
||||
auto f = qlut[insn & 0x3][lut_val];
|
||||
auto f = decode_instr(root, instr);
|
||||
if (f == nullptr) {
|
||||
f = &this_class::illegal_intruction;
|
||||
}
|
||||
return (this->*f)(pc, insn, tu);
|
||||
return (this->*f)(pc, instr, tu);
|
||||
}
|
||||
|
||||
template <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(tu.constant(std::numeric_limits<uint32_t>::max(), 32),traits<ARCH>::LAST_BRANCH);
|
||||
tu.store(traits::LAST_BRANCH, tu.constant(std::numeric_limits<uint32_t>::max(), 32));
|
||||
}
|
||||
|
||||
template <typename ARCH> void vm_impl<ARCH>::gen_leave_trap(tu_builder& tu, unsigned lvl) {
|
||||
tu("leave_trap(core_ptr, {});", lvl);
|
||||
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);
|
||||
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));
|
||||
}
|
||||
|
||||
template <typename ARCH> void vm_impl<ARCH>::gen_wait(tu_builder& tu, unsigned type) {
|
||||
|
@ -274,12 +306,13 @@ 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:");
|
||||
tu("enter_trap(core_ptr, *trap_state, *pc);");
|
||||
tu.store(tu.constant(std::numeric_limits<uint32_t>::max(),32),traits<ARCH>::LAST_BRANCH);
|
||||
this->gen_sync(tu, POST_SYNC, -1);
|
||||
tu("enter_trap(core_ptr, *trap_state, *pc, 0);");
|
||||
tu.store(traits::LAST_BRANCH, tu.constant(std::numeric_limits<uint32_t>::max(),32));
|
||||
tu("return *next_pc;");
|
||||
}
|
||||
|
||||
} // namespace mnrv32
|
||||
} // 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) {
|
||||
|
@ -287,5 +320,28 @@ 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/factory.h>
|
||||
#include <iss/arch/riscv_hart_m_p.h>
|
||||
#include <iss/arch/riscv_hart_mu_p.h>
|
||||
namespace iss {
|
||||
namespace {
|
||||
volatile std::array<bool, 2> dummy = {
|
||||
core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|m_p|tcc", [](unsigned port, void*) -> 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);
|
||||
return {cpu_ptr{cpu}, vm_ptr{vm}};
|
||||
}),
|
||||
core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p|tcc", [](unsigned port, void*) -> 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);
|
||||
return {cpu_ptr{cpu}, vm_ptr{vm}};
|
||||
})
|
||||
};
|
||||
}
|
||||
}
|
||||
// clang-format on
|
|
@ -1,9 +0,0 @@
|
|||
{
|
||||
"${coreDef.name}" : [<%instructions.eachWithIndex{instr,index -> %>${index==0?"":","}
|
||||
{
|
||||
"name" : "${instr.name}",
|
||||
"size" : ${instr.length},
|
||||
"delay" : ${generator.hasAttribute(instr.instruction, com.minres.coredsl.coreDsl.InstrAttribute.COND)?[1,1]:1}
|
||||
}<%}%>
|
||||
]
|
||||
}
|
|
@ -1,223 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (C) 2017, 2018 MINRES Technologies GmbH
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
<%
|
||||
import com.minres.coredsl.coreDsl.Register
|
||||
import com.minres.coredsl.coreDsl.RegisterFile
|
||||
import com.minres.coredsl.coreDsl.RegisterAlias
|
||||
def getTypeSize(size){
|
||||
if(size > 32) 64 else if(size > 16) 32 else if(size > 8) 16 else 8
|
||||
}
|
||||
def getOriginalName(reg){
|
||||
if( reg.original instanceof RegisterFile) {
|
||||
if( reg.index != null ) {
|
||||
return reg.original.name+generator.generateHostCode(reg.index)
|
||||
} else {
|
||||
return reg.original.name
|
||||
}
|
||||
} else if(reg.original instanceof Register){
|
||||
return reg.original.name
|
||||
}
|
||||
}
|
||||
def getRegisterNames(){
|
||||
def regNames = []
|
||||
allRegs.each { reg ->
|
||||
if( reg instanceof RegisterFile) {
|
||||
(reg.range.right..reg.range.left).each{
|
||||
regNames+=reg.name.toLowerCase()+it
|
||||
}
|
||||
} else if(reg instanceof Register){
|
||||
regNames+=reg.name.toLowerCase()
|
||||
}
|
||||
}
|
||||
return regNames
|
||||
}
|
||||
def getRegisterAliasNames(){
|
||||
def regMap = allRegs.findAll{it instanceof RegisterAlias }.collectEntries {[getOriginalName(it), it.name]}
|
||||
return allRegs.findAll{it instanceof Register || it instanceof RegisterFile}.collect{reg ->
|
||||
if( reg instanceof RegisterFile) {
|
||||
return (reg.range.right..reg.range.left).collect{ (regMap[reg.name]?:regMap[reg.name+it]?:reg.name.toLowerCase()+it).toLowerCase() }
|
||||
} else if(reg instanceof Register){
|
||||
regMap[reg.name]?:reg.name.toLowerCase()
|
||||
}
|
||||
}.flatten()
|
||||
}
|
||||
%>
|
||||
#ifndef _${coreDef.name.toUpperCase()}_H_
|
||||
#define _${coreDef.name.toUpperCase()}_H_
|
||||
|
||||
#include <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_ */
|
|
@ -1,107 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (C) 2017, 2018 MINRES Technologies GmbH
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*******************************************************************************/
|
||||
<%
|
||||
import com.minres.coredsl.coreDsl.Register
|
||||
import com.minres.coredsl.coreDsl.RegisterFile
|
||||
import com.minres.coredsl.coreDsl.RegisterAlias
|
||||
def getOriginalName(reg){
|
||||
if( reg.original instanceof RegisterFile) {
|
||||
if( reg.index != null ) {
|
||||
return reg.original.name+generator.generateHostCode(reg.index)
|
||||
} else {
|
||||
return reg.original.name
|
||||
}
|
||||
} else if(reg.original instanceof Register){
|
||||
return reg.original.name
|
||||
}
|
||||
}
|
||||
def getRegisterNames(){
|
||||
def regNames = []
|
||||
allRegs.each { reg ->
|
||||
if( reg instanceof RegisterFile) {
|
||||
(reg.range.right..reg.range.left).each{
|
||||
regNames+=reg.name.toLowerCase()+it
|
||||
}
|
||||
} else if(reg instanceof Register){
|
||||
regNames+=reg.name.toLowerCase()
|
||||
}
|
||||
}
|
||||
return regNames
|
||||
}
|
||||
def getRegisterAliasNames(){
|
||||
def regMap = allRegs.findAll{it instanceof RegisterAlias }.collectEntries {[getOriginalName(it), it.name]}
|
||||
return allRegs.findAll{it instanceof Register || it instanceof RegisterFile}.collect{reg ->
|
||||
if( reg instanceof RegisterFile) {
|
||||
return (reg.range.right..reg.range.left).collect{ (regMap[reg.name]?:regMap[reg.name+it]?:reg.name.toLowerCase()+it).toLowerCase() }
|
||||
} else if(reg instanceof Register){
|
||||
regMap[reg.name]?:reg.name.toLowerCase()
|
||||
}
|
||||
}.flatten()
|
||||
}
|
||||
%>
|
||||
#include "util/ities.h"
|
||||
#include <util/logging.h>
|
||||
#include <iss/arch/${coreDef.name.toLowerCase()}.h>
|
||||
#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*>(®);
|
||||
}
|
||||
|
||||
${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
|
||||
}
|
||||
|
|
@ -1 +0,0 @@
|
|||
/tgc_*.h
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,43 +0,0 @@
|
|||
#ifndef _ISS_ARCH_TGC_MAPPER_H
|
||||
#define _ISS_ARCH_TGC_MAPPER_H
|
||||
|
||||
#include "riscv_hart_m_p.h"
|
||||
#include "tgc_c.h"
|
||||
using tgc_c_plat_type = iss::arch::riscv_hart_m_p<iss::arch::tgc_c>;
|
||||
#ifdef CORE_TGC_B
|
||||
#include "riscv_hart_m_p.h"
|
||||
#include "tgc_b.h"
|
||||
using tgc_b_plat_type = iss::arch::riscv_hart_m_p<iss::arch::tgc_b>;
|
||||
#endif
|
||||
#ifdef CORE_TGC_C_XRB_NN
|
||||
#include "riscv_hart_m_p.h"
|
||||
#include "tgc_c_xrb_nn.h"
|
||||
using tgc_c_xrb_nn_plat_type = iss::arch::riscv_hart_m_p<iss::arch::tgc_c_xrb_nn>;
|
||||
#endif
|
||||
#ifdef CORE_TGC_D
|
||||
#include "riscv_hart_mu_p.h"
|
||||
#include "tgc_d.h"
|
||||
using tgc_d_plat_type = iss::arch::riscv_hart_mu_p<iss::arch::tgc_d, (iss::arch::features_e)(iss::arch::FEAT_PMP | iss::arch::FEAT_CLIC | iss::arch::FEAT_EXT_N)>;
|
||||
#endif
|
||||
#ifdef CORE_TGC_D_XRB_MAC
|
||||
#include "riscv_hart_mu_p.h"
|
||||
#include "tgc_d_xrb_mac.h"
|
||||
using tgc_d_xrb_mac_plat_type = iss::arch::riscv_hart_mu_p<iss::arch::tgc_d_xrb_mac, (iss::arch::features_e)(iss::arch::FEAT_PMP | iss::arch::FEAT_CLIC | iss::arch::FEAT_EXT_N)>;
|
||||
#endif
|
||||
#ifdef CORE_TGC_D_XRB_NN
|
||||
#include "riscv_hart_mu_p.h"
|
||||
#include "tgc_d_xrb_nn.h"
|
||||
using tgc_d_xrb_nn_plat_type = iss::arch::riscv_hart_mu_p<iss::arch::tgc_d_xrb_nn, (iss::arch::features_e)(iss::arch::FEAT_PMP | iss::arch::FEAT_CLIC | iss::arch::FEAT_EXT_N)>;
|
||||
#endif
|
||||
#ifdef CORE_TGC_E
|
||||
#include "riscv_hart_mu_p.h"
|
||||
#include "tgc_e.h"
|
||||
using tgc_e_plat_type = iss::arch::riscv_hart_mu_p<iss::arch::tgc_e, (iss::arch::features_e)(iss::arch::FEAT_PMP | iss::arch::FEAT_CLIC | iss::arch::FEAT_EXT_N)>;
|
||||
#endif
|
||||
#ifdef CORE_TGC_X
|
||||
#include "riscv_hart_mu_p.h"
|
||||
#include "tgc_x.h"
|
||||
using tgc_x_plat_type = iss::arch::riscv_hart_mu_p<iss::arch::tgc_x, (iss::arch::features_e)(iss::arch::FEAT_PMP | iss::arch::FEAT_CLIC | iss::arch::FEAT_EXT_N | iss::arch::FEAT_TCM)>;
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -8,7 +8,7 @@ project("sotfloat" VERSION 3.0.0)
|
|||
# Set the version number of your project here (format is MAJOR.MINOR.PATCHLEVEL - e.g. 1.0.0)
|
||||
set(VERSION "3e")
|
||||
|
||||
include(Common)
|
||||
#include(Common)
|
||||
include(GNUInstallDirs)
|
||||
|
||||
set(SPECIALIZATION RISCV)
|
||||
|
|
|
@ -50,4 +50,3 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
*----------------------------------------------------------------------------*/
|
||||
#define SOFTFLOAT_BUILTIN_CLZ 1
|
||||
#include "opts-GCC.h"
|
||||
|
||||
|
|
|
@ -50,4 +50,3 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
*----------------------------------------------------------------------------*/
|
||||
#define SOFTFLOAT_BUILTIN_CLZ 1
|
||||
#include "opts-GCC.h"
|
||||
|
||||
|
|
|
@ -50,4 +50,3 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
*----------------------------------------------------------------------------*/
|
||||
#define SOFTFLOAT_BUILTIN_CLZ 1
|
||||
#include "opts-GCC.h"
|
||||
|
||||
|
|
|
@ -54,4 +54,3 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#define SOFTFLOAT_INTRINSIC_INT128 1
|
||||
#endif
|
||||
#include "opts-GCC.h"
|
||||
|
||||
|
|
|
@ -50,4 +50,3 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
*----------------------------------------------------------------------------*/
|
||||
#define SOFTFLOAT_BUILTIN_CLZ 1
|
||||
#include "opts-GCC.h"
|
||||
|
||||
|
|
|
@ -50,4 +50,3 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
*----------------------------------------------------------------------------*/
|
||||
#define SOFTFLOAT_BUILTIN_CLZ 1
|
||||
#include "opts-GCC.h"
|
||||
|
||||
|
|
|
@ -51,4 +51,3 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#define SOFTFLOAT_BUILTIN_CLZ 1
|
||||
#define SOFTFLOAT_INTRINSIC_INT128 1
|
||||
#include "opts-GCC.h"
|
||||
|
||||
|
|
|
@ -47,4 +47,3 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
/*----------------------------------------------------------------------------
|
||||
*----------------------------------------------------------------------------*/
|
||||
== > #define THREAD_LOCAL _Thread_local
|
||||
|
||||
|
|
|
@ -47,4 +47,3 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
/*----------------------------------------------------------------------------
|
||||
*----------------------------------------------------------------------------*/
|
||||
== > #define THREAD_LOCAL _Thread_local
|
||||
|
||||
|
|
|
@ -37,10 +37,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#ifndef specialize_h
|
||||
#define specialize_h 1
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "primitiveTypes.h"
|
||||
#include "softfloat.h"
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Default value for 'softfloat_detectTininess'.
|
||||
|
@ -114,8 +114,7 @@ uint_fast16_t softfloat_commonNaNToF16UI( const struct commonNaN *aPtr );
|
|||
| the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a
|
||||
| signaling NaN, the invalid exception is raised.
|
||||
*----------------------------------------------------------------------------*/
|
||||
uint_fast16_t
|
||||
softfloat_propagateNaNF16UI( uint_fast16_t uiA, uint_fast16_t uiB );
|
||||
uint_fast16_t softfloat_propagateNaNF16UI(uint_fast16_t uiA, uint_fast16_t uiB);
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| The bit pattern for a default generated 32-bit floating-point NaN.
|
||||
|
@ -149,8 +148,7 @@ 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.
|
||||
|
@ -162,7 +160,8 @@ uint_fast32_t
|
|||
| 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
|
||||
|
@ -184,8 +183,7 @@ 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.
|
||||
|
@ -199,7 +197,8 @@ uint_fast64_t
|
|||
| floating-point signaling NaN.
|
||||
| Note: This macro evaluates its arguments more than once.
|
||||
*----------------------------------------------------------------------------*/
|
||||
#define softfloat_isSigNaNExtF80UI( uiA64, uiA0 ) ((((uiA64) & 0x7FFF) == 0x7FFF) && ! ((uiA0) & UINT64_C( 0x4000000000000000 )) && ((uiA0) & UINT64_C( 0x3FFFFFFFFFFFFFFF )))
|
||||
#define softfloat_isSigNaNExtF80UI(uiA64, uiA0) \
|
||||
((((uiA64)&0x7FFF) == 0x7FFF) && !((uiA0)&UINT64_C(0x4000000000000000)) && ((uiA0)&UINT64_C(0x3FFFFFFFFFFFFFFF)))
|
||||
|
||||
#ifdef SOFTFLOAT_FAST_INT64
|
||||
|
||||
|
@ -215,9 +214,7 @@ uint_fast64_t
|
|||
| location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid
|
||||
| exception is raised.
|
||||
*----------------------------------------------------------------------------*/
|
||||
void
|
||||
softfloat_extF80UIToCommonNaN(
|
||||
uint_fast16_t uiA64, uint_fast64_t uiA0, struct commonNaN *zPtr );
|
||||
void softfloat_extF80UIToCommonNaN(uint_fast16_t uiA64, uint_fast64_t uiA0, struct commonNaN* zPtr);
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Converts the common NaN pointed to by 'aPtr' into an 80-bit extended
|
||||
|
@ -235,13 +232,7 @@ 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.
|
||||
|
@ -255,7 +246,8 @@ struct uint128
|
|||
| point signaling NaN.
|
||||
| Note: This macro evaluates its arguments more than once.
|
||||
*----------------------------------------------------------------------------*/
|
||||
#define softfloat_isSigNaNF128UI( uiA64, uiA0 ) ((((uiA64) & UINT64_C( 0x7FFF800000000000 )) == UINT64_C( 0x7FFF000000000000 )) && ((uiA0) || ((uiA64) & UINT64_C( 0x00007FFFFFFFFFFF ))))
|
||||
#define softfloat_isSigNaNF128UI(uiA64, uiA0) \
|
||||
((((uiA64)&UINT64_C(0x7FFF800000000000)) == UINT64_C(0x7FFF000000000000)) && ((uiA0) || ((uiA64)&UINT64_C(0x00007FFFFFFFFFFF))))
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Assuming the unsigned integer formed from concatenating 'uiA64' and 'uiA0'
|
||||
|
@ -264,9 +256,7 @@ struct uint128
|
|||
| pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid exception
|
||||
| is raised.
|
||||
*----------------------------------------------------------------------------*/
|
||||
void
|
||||
softfloat_f128UIToCommonNaN(
|
||||
uint_fast64_t uiA64, uint_fast64_t uiA0, struct commonNaN *zPtr );
|
||||
void softfloat_f128UIToCommonNaN(uint_fast64_t uiA64, uint_fast64_t uiA0, struct commonNaN* zPtr);
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Converts the common NaN pointed to by 'aPtr' into a 128-bit floating-point
|
||||
|
@ -283,13 +273,7 @@ struct uint128 softfloat_commonNaNToF128UI( const struct commonNaN * );
|
|||
| If either original floating-point value is a signaling NaN, the invalid
|
||||
| exception is raised.
|
||||
*----------------------------------------------------------------------------*/
|
||||
struct uint128
|
||||
softfloat_propagateNaNF128UI(
|
||||
uint_fast64_t uiA64,
|
||||
uint_fast64_t uiA0,
|
||||
uint_fast64_t uiB64,
|
||||
uint_fast64_t uiB0
|
||||
);
|
||||
struct uint128 softfloat_propagateNaNF128UI(uint_fast64_t uiA64, uint_fast64_t uiA0, uint_fast64_t uiB64, uint_fast64_t uiB0);
|
||||
|
||||
#else
|
||||
|
||||
|
@ -304,18 +288,14 @@ struct uint128
|
|||
| common NaN at the location pointed to by 'zPtr'. If the NaN is a signaling
|
||||
| NaN, the invalid exception is raised.
|
||||
*----------------------------------------------------------------------------*/
|
||||
void
|
||||
softfloat_extF80MToCommonNaN(
|
||||
const struct extFloat80M *aSPtr, struct commonNaN *zPtr );
|
||||
void softfloat_extF80MToCommonNaN(const struct extFloat80M* aSPtr, struct commonNaN* zPtr);
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Converts the common NaN pointed to by 'aPtr' into an 80-bit extended
|
||||
| floating-point NaN, and stores this NaN at the location pointed to by
|
||||
| 'zSPtr'.
|
||||
*----------------------------------------------------------------------------*/
|
||||
void
|
||||
softfloat_commonNaNToExtF80M(
|
||||
const struct commonNaN *aPtr, struct extFloat80M *zSPtr );
|
||||
void softfloat_commonNaNToExtF80M(const struct commonNaN* aPtr, struct extFloat80M* zSPtr);
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Assuming at least one of the two 80-bit extended floating-point values
|
||||
|
@ -323,12 +303,7 @@ void
|
|||
| at the location pointed to by 'zSPtr'. If either original floating-point
|
||||
| value is a signaling NaN, the invalid exception is raised.
|
||||
*----------------------------------------------------------------------------*/
|
||||
void
|
||||
softfloat_propagateNaNExtF80M(
|
||||
const struct extFloat80M *aSPtr,
|
||||
const struct extFloat80M *bSPtr,
|
||||
struct extFloat80M *zSPtr
|
||||
);
|
||||
void softfloat_propagateNaNExtF80M(const struct extFloat80M* aSPtr, const struct extFloat80M* bSPtr, struct extFloat80M* zSPtr);
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| The bit pattern for a default generated 128-bit floating-point NaN.
|
||||
|
@ -346,8 +321,7 @@ void
|
|||
| four 32-bit elements that concatenate in the platform's normal endian order
|
||||
| to form a 128-bit floating-point value.
|
||||
*----------------------------------------------------------------------------*/
|
||||
void
|
||||
softfloat_f128MToCommonNaN( const uint32_t *aWPtr, struct commonNaN *zPtr );
|
||||
void softfloat_f128MToCommonNaN(const uint32_t* aWPtr, struct commonNaN* zPtr);
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Converts the common NaN pointed to by 'aPtr' into a 128-bit floating-point
|
||||
|
@ -355,8 +329,7 @@ void
|
|||
| 'zWPtr' points to an array of four 32-bit elements that concatenate in the
|
||||
| platform's normal endian order to form a 128-bit floating-point value.
|
||||
*----------------------------------------------------------------------------*/
|
||||
void
|
||||
softfloat_commonNaNToF128M( const struct commonNaN *aPtr, uint32_t *zWPtr );
|
||||
void softfloat_commonNaNToF128M(const struct commonNaN* aPtr, uint32_t* zWPtr);
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Assuming at least one of the two 128-bit floating-point values pointed to by
|
||||
|
@ -366,11 +339,8 @@ void
|
|||
| and 'zWPtr' points to an array of four 32-bit elements that concatenate in
|
||||
| the platform's normal endian order to form a 128-bit floating-point value.
|
||||
*----------------------------------------------------------------------------*/
|
||||
void
|
||||
softfloat_propagateNaNF128M(
|
||||
const uint32_t *aWPtr, const uint32_t *bWPtr, uint32_t *zWPtr );
|
||||
void softfloat_propagateNaNF128M(const uint32_t* aWPtr, const uint32_t* bWPtr, uint32_t* zWPtr);
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -37,10 +37,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#ifndef specialize_h
|
||||
#define specialize_h 1
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "primitiveTypes.h"
|
||||
#include "softfloat.h"
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Default value for 'softfloat_detectTininess'.
|
||||
|
@ -114,8 +114,7 @@ uint_fast16_t softfloat_commonNaNToF16UI( const struct commonNaN *aPtr );
|
|||
| the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a
|
||||
| signaling NaN, the invalid exception is raised.
|
||||
*----------------------------------------------------------------------------*/
|
||||
uint_fast16_t
|
||||
softfloat_propagateNaNF16UI( uint_fast16_t uiA, uint_fast16_t uiB );
|
||||
uint_fast16_t softfloat_propagateNaNF16UI(uint_fast16_t uiA, uint_fast16_t uiB);
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| The bit pattern for a default generated 32-bit floating-point NaN.
|
||||
|
@ -149,8 +148,7 @@ 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.
|
||||
|
@ -162,7 +160,8 @@ uint_fast32_t
|
|||
| 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
|
||||
|
@ -184,8 +183,7 @@ 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.
|
||||
|
@ -199,7 +197,8 @@ uint_fast64_t
|
|||
| floating-point signaling NaN.
|
||||
| Note: This macro evaluates its arguments more than once.
|
||||
*----------------------------------------------------------------------------*/
|
||||
#define softfloat_isSigNaNExtF80UI( uiA64, uiA0 ) ((((uiA64) & 0x7FFF) == 0x7FFF) && ! ((uiA0) & UINT64_C( 0x4000000000000000 )) && ((uiA0) & UINT64_C( 0x3FFFFFFFFFFFFFFF )))
|
||||
#define softfloat_isSigNaNExtF80UI(uiA64, uiA0) \
|
||||
((((uiA64)&0x7FFF) == 0x7FFF) && !((uiA0)&UINT64_C(0x4000000000000000)) && ((uiA0)&UINT64_C(0x3FFFFFFFFFFFFFFF)))
|
||||
|
||||
#ifdef SOFTFLOAT_FAST_INT64
|
||||
|
||||
|
@ -215,9 +214,7 @@ uint_fast64_t
|
|||
| location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid
|
||||
| exception is raised.
|
||||
*----------------------------------------------------------------------------*/
|
||||
void
|
||||
softfloat_extF80UIToCommonNaN(
|
||||
uint_fast16_t uiA64, uint_fast64_t uiA0, struct commonNaN *zPtr );
|
||||
void softfloat_extF80UIToCommonNaN(uint_fast16_t uiA64, uint_fast64_t uiA0, struct commonNaN* zPtr);
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Converts the common NaN pointed to by 'aPtr' into an 80-bit extended
|
||||
|
@ -235,13 +232,7 @@ 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.
|
||||
|
@ -255,7 +246,8 @@ struct uint128
|
|||
| point signaling NaN.
|
||||
| Note: This macro evaluates its arguments more than once.
|
||||
*----------------------------------------------------------------------------*/
|
||||
#define softfloat_isSigNaNF128UI( uiA64, uiA0 ) ((((uiA64) & UINT64_C( 0x7FFF800000000000 )) == UINT64_C( 0x7FFF000000000000 )) && ((uiA0) || ((uiA64) & UINT64_C( 0x00007FFFFFFFFFFF ))))
|
||||
#define softfloat_isSigNaNF128UI(uiA64, uiA0) \
|
||||
((((uiA64)&UINT64_C(0x7FFF800000000000)) == UINT64_C(0x7FFF000000000000)) && ((uiA0) || ((uiA64)&UINT64_C(0x00007FFFFFFFFFFF))))
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Assuming the unsigned integer formed from concatenating 'uiA64' and 'uiA0'
|
||||
|
@ -264,9 +256,7 @@ struct uint128
|
|||
| pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid exception
|
||||
| is raised.
|
||||
*----------------------------------------------------------------------------*/
|
||||
void
|
||||
softfloat_f128UIToCommonNaN(
|
||||
uint_fast64_t uiA64, uint_fast64_t uiA0, struct commonNaN *zPtr );
|
||||
void softfloat_f128UIToCommonNaN(uint_fast64_t uiA64, uint_fast64_t uiA0, struct commonNaN* zPtr);
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Converts the common NaN pointed to by 'aPtr' into a 128-bit floating-point
|
||||
|
@ -283,13 +273,7 @@ struct uint128 softfloat_commonNaNToF128UI( const struct commonNaN * );
|
|||
| If either original floating-point value is a signaling NaN, the invalid
|
||||
| exception is raised.
|
||||
*----------------------------------------------------------------------------*/
|
||||
struct uint128
|
||||
softfloat_propagateNaNF128UI(
|
||||
uint_fast64_t uiA64,
|
||||
uint_fast64_t uiA0,
|
||||
uint_fast64_t uiB64,
|
||||
uint_fast64_t uiB0
|
||||
);
|
||||
struct uint128 softfloat_propagateNaNF128UI(uint_fast64_t uiA64, uint_fast64_t uiA0, uint_fast64_t uiB64, uint_fast64_t uiB0);
|
||||
|
||||
#else
|
||||
|
||||
|
@ -304,18 +288,14 @@ struct uint128
|
|||
| common NaN at the location pointed to by 'zPtr'. If the NaN is a signaling
|
||||
| NaN, the invalid exception is raised.
|
||||
*----------------------------------------------------------------------------*/
|
||||
void
|
||||
softfloat_extF80MToCommonNaN(
|
||||
const struct extFloat80M *aSPtr, struct commonNaN *zPtr );
|
||||
void softfloat_extF80MToCommonNaN(const struct extFloat80M* aSPtr, struct commonNaN* zPtr);
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Converts the common NaN pointed to by 'aPtr' into an 80-bit extended
|
||||
| floating-point NaN, and stores this NaN at the location pointed to by
|
||||
| 'zSPtr'.
|
||||
*----------------------------------------------------------------------------*/
|
||||
void
|
||||
softfloat_commonNaNToExtF80M(
|
||||
const struct commonNaN *aPtr, struct extFloat80M *zSPtr );
|
||||
void softfloat_commonNaNToExtF80M(const struct commonNaN* aPtr, struct extFloat80M* zSPtr);
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Assuming at least one of the two 80-bit extended floating-point values
|
||||
|
@ -323,12 +303,7 @@ void
|
|||
| at the location pointed to by 'zSPtr'. If either original floating-point
|
||||
| value is a signaling NaN, the invalid exception is raised.
|
||||
*----------------------------------------------------------------------------*/
|
||||
void
|
||||
softfloat_propagateNaNExtF80M(
|
||||
const struct extFloat80M *aSPtr,
|
||||
const struct extFloat80M *bSPtr,
|
||||
struct extFloat80M *zSPtr
|
||||
);
|
||||
void softfloat_propagateNaNExtF80M(const struct extFloat80M* aSPtr, const struct extFloat80M* bSPtr, struct extFloat80M* zSPtr);
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| The bit pattern for a default generated 128-bit floating-point NaN.
|
||||
|
@ -346,8 +321,7 @@ void
|
|||
| four 32-bit elements that concatenate in the platform's normal endian order
|
||||
| to form a 128-bit floating-point value.
|
||||
*----------------------------------------------------------------------------*/
|
||||
void
|
||||
softfloat_f128MToCommonNaN( const uint32_t *aWPtr, struct commonNaN *zPtr );
|
||||
void softfloat_f128MToCommonNaN(const uint32_t* aWPtr, struct commonNaN* zPtr);
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Converts the common NaN pointed to by 'aPtr' into a 128-bit floating-point
|
||||
|
@ -355,8 +329,7 @@ void
|
|||
| 'zWPtr' points to an array of four 32-bit elements that concatenate in the
|
||||
| platform's normal endian order to form a 128-bit floating-point value.
|
||||
*----------------------------------------------------------------------------*/
|
||||
void
|
||||
softfloat_commonNaNToF128M( const struct commonNaN *aPtr, uint32_t *zWPtr );
|
||||
void softfloat_commonNaNToF128M(const struct commonNaN* aPtr, uint32_t* zWPtr);
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Assuming at least one of the two 128-bit floating-point values pointed to by
|
||||
|
@ -366,11 +339,8 @@ void
|
|||
| and 'zWPtr' points to an array of four 32-bit elements that concatenate in
|
||||
| the platform's normal endian order to form a 128-bit floating-point value.
|
||||
*----------------------------------------------------------------------------*/
|
||||
void
|
||||
softfloat_propagateNaNF128M(
|
||||
const uint32_t *aWPtr, const uint32_t *bWPtr, uint32_t *zWPtr );
|
||||
void softfloat_propagateNaNF128M(const uint32_t* aWPtr, const uint32_t* bWPtr, uint32_t* zWPtr);
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -37,10 +37,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#ifndef specialize_h
|
||||
#define specialize_h 1
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "primitiveTypes.h"
|
||||
#include "softfloat.h"
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Default value for 'softfloat_detectTininess'.
|
||||
|
@ -73,7 +73,9 @@ 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.
|
||||
|
@ -93,7 +95,9 @@ struct commonNaN { char _unused; };
|
|||
| location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid
|
||||
| exception is raised.
|
||||
*----------------------------------------------------------------------------*/
|
||||
#define softfloat_f16UIToCommonNaN( uiA, zPtr ) if ( ! ((uiA) & 0x0200) ) softfloat_raiseFlags( softfloat_flag_invalid )
|
||||
#define softfloat_f16UIToCommonNaN(uiA, zPtr) \
|
||||
if(!((uiA)&0x0200)) \
|
||||
softfloat_raiseFlags(softfloat_flag_invalid)
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Converts the common NaN pointed to by 'aPtr' into a 16-bit floating-point
|
||||
|
@ -107,8 +111,7 @@ struct commonNaN { char _unused; };
|
|||
| the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a
|
||||
| signaling NaN, the invalid exception is raised.
|
||||
*----------------------------------------------------------------------------*/
|
||||
uint_fast16_t
|
||||
softfloat_propagateNaNF16UI( uint_fast16_t uiA, uint_fast16_t uiB );
|
||||
uint_fast16_t softfloat_propagateNaNF16UI(uint_fast16_t uiA, uint_fast16_t uiB);
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| The bit pattern for a default generated 32-bit floating-point NaN.
|
||||
|
@ -128,7 +131,9 @@ uint_fast16_t
|
|||
| location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid
|
||||
| exception is raised.
|
||||
*----------------------------------------------------------------------------*/
|
||||
#define softfloat_f32UIToCommonNaN( uiA, zPtr ) if ( ! ((uiA) & 0x00400000) ) softfloat_raiseFlags( softfloat_flag_invalid )
|
||||
#define softfloat_f32UIToCommonNaN(uiA, zPtr) \
|
||||
if(!((uiA)&0x00400000)) \
|
||||
softfloat_raiseFlags(softfloat_flag_invalid)
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Converts the common NaN pointed to by 'aPtr' into a 32-bit floating-point
|
||||
|
@ -142,8 +147,7 @@ uint_fast16_t
|
|||
| the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a
|
||||
| signaling NaN, the invalid exception is raised.
|
||||
*----------------------------------------------------------------------------*/
|
||||
uint_fast32_t
|
||||
softfloat_propagateNaNF32UI( uint_fast32_t uiA, uint_fast32_t uiB );
|
||||
uint_fast32_t softfloat_propagateNaNF32UI(uint_fast32_t uiA, uint_fast32_t uiB);
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| The bit pattern for a default generated 64-bit floating-point NaN.
|
||||
|
@ -155,7 +159,8 @@ uint_fast32_t
|
|||
| 64-bit floating-point signaling NaN.
|
||||
| Note: This macro evaluates its argument more than once.
|
||||
*----------------------------------------------------------------------------*/
|
||||
#define softfloat_isSigNaNF64UI( uiA ) ((((uiA) & UINT64_C( 0x7FF8000000000000 )) == UINT64_C( 0x7FF0000000000000 )) && ((uiA) & UINT64_C( 0x0007FFFFFFFFFFFF )))
|
||||
#define softfloat_isSigNaNF64UI(uiA) \
|
||||
((((uiA)&UINT64_C(0x7FF8000000000000)) == UINT64_C(0x7FF0000000000000)) && ((uiA)&UINT64_C(0x0007FFFFFFFFFFFF)))
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Assuming 'uiA' has the bit pattern of a 64-bit floating-point NaN, converts
|
||||
|
@ -163,7 +168,9 @@ uint_fast32_t
|
|||
| location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid
|
||||
| exception is raised.
|
||||
*----------------------------------------------------------------------------*/
|
||||
#define softfloat_f64UIToCommonNaN( uiA, zPtr ) if ( ! ((uiA) & UINT64_C( 0x0008000000000000 )) ) softfloat_raiseFlags( softfloat_flag_invalid )
|
||||
#define softfloat_f64UIToCommonNaN(uiA, zPtr) \
|
||||
if(!((uiA)&UINT64_C(0x0008000000000000))) \
|
||||
softfloat_raiseFlags(softfloat_flag_invalid)
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Converts the common NaN pointed to by 'aPtr' into a 64-bit floating-point
|
||||
|
@ -177,8 +184,7 @@ uint_fast32_t
|
|||
| the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a
|
||||
| signaling NaN, the invalid exception is raised.
|
||||
*----------------------------------------------------------------------------*/
|
||||
uint_fast64_t
|
||||
softfloat_propagateNaNF64UI( uint_fast64_t uiA, uint_fast64_t uiB );
|
||||
uint_fast64_t softfloat_propagateNaNF64UI(uint_fast64_t uiA, uint_fast64_t uiB);
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| The bit pattern for a default generated 80-bit extended floating-point NaN.
|
||||
|
@ -192,7 +198,8 @@ uint_fast64_t
|
|||
| floating-point signaling NaN.
|
||||
| Note: This macro evaluates its arguments more than once.
|
||||
*----------------------------------------------------------------------------*/
|
||||
#define softfloat_isSigNaNExtF80UI( uiA64, uiA0 ) ((((uiA64) & 0x7FFF) == 0x7FFF) && ! ((uiA0) & UINT64_C( 0x4000000000000000 )) && ((uiA0) & UINT64_C( 0x3FFFFFFFFFFFFFFF )))
|
||||
#define softfloat_isSigNaNExtF80UI(uiA64, uiA0) \
|
||||
((((uiA64)&0x7FFF) == 0x7FFF) && !((uiA0)&UINT64_C(0x4000000000000000)) && ((uiA0)&UINT64_C(0x3FFFFFFFFFFFFFFF)))
|
||||
|
||||
#ifdef SOFTFLOAT_FAST_INT64
|
||||
|
||||
|
@ -208,7 +215,9 @@ uint_fast64_t
|
|||
| location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid
|
||||
| exception is raised.
|
||||
*----------------------------------------------------------------------------*/
|
||||
#define softfloat_extF80UIToCommonNaN( uiA64, uiA0, zPtr ) if ( ! ((uiA0) & UINT64_C( 0x4000000000000000 )) ) softfloat_raiseFlags( softfloat_flag_invalid )
|
||||
#define softfloat_extF80UIToCommonNaN(uiA64, uiA0, zPtr) \
|
||||
if(!((uiA0)&UINT64_C(0x4000000000000000))) \
|
||||
softfloat_raiseFlags(softfloat_flag_invalid)
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Converts the common NaN pointed to by 'aPtr' into an 80-bit extended
|
||||
|
@ -217,8 +226,7 @@ uint_fast64_t
|
|||
*----------------------------------------------------------------------------*/
|
||||
#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;
|
||||
|
@ -237,13 +245,7 @@ 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.
|
||||
|
@ -257,7 +259,8 @@ struct uint128
|
|||
| point signaling NaN.
|
||||
| Note: This macro evaluates its arguments more than once.
|
||||
*----------------------------------------------------------------------------*/
|
||||
#define softfloat_isSigNaNF128UI( uiA64, uiA0 ) ((((uiA64) & UINT64_C( 0x7FFF800000000000 )) == UINT64_C( 0x7FFF000000000000 )) && ((uiA0) || ((uiA64) & UINT64_C( 0x00007FFFFFFFFFFF ))))
|
||||
#define softfloat_isSigNaNF128UI(uiA64, uiA0) \
|
||||
((((uiA64)&UINT64_C(0x7FFF800000000000)) == UINT64_C(0x7FFF000000000000)) && ((uiA0) || ((uiA64)&UINT64_C(0x00007FFFFFFFFFFF))))
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Assuming the unsigned integer formed from concatenating 'uiA64' and 'uiA0'
|
||||
|
@ -266,7 +269,9 @@ struct uint128
|
|||
| pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid exception
|
||||
| is raised.
|
||||
*----------------------------------------------------------------------------*/
|
||||
#define softfloat_f128UIToCommonNaN( uiA64, uiA0, zPtr ) if ( ! ((uiA64) & UINT64_C( 0x0000800000000000 )) ) softfloat_raiseFlags( softfloat_flag_invalid )
|
||||
#define softfloat_f128UIToCommonNaN(uiA64, uiA0, zPtr) \
|
||||
if(!((uiA64)&UINT64_C(0x0000800000000000))) \
|
||||
softfloat_raiseFlags(softfloat_flag_invalid)
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Converts the common NaN pointed to by 'aPtr' into a 128-bit floating-point
|
||||
|
@ -274,8 +279,7 @@ struct uint128
|
|||
*----------------------------------------------------------------------------*/
|
||||
#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;
|
||||
|
@ -294,13 +298,7 @@ struct uint128 softfloat_commonNaNToF128UI( const struct commonNaN * );
|
|||
| If either original floating-point value is a signaling NaN, the invalid
|
||||
| exception is raised.
|
||||
*----------------------------------------------------------------------------*/
|
||||
struct uint128
|
||||
softfloat_propagateNaNF128UI(
|
||||
uint_fast64_t uiA64,
|
||||
uint_fast64_t uiA0,
|
||||
uint_fast64_t uiB64,
|
||||
uint_fast64_t uiB0
|
||||
);
|
||||
struct uint128 softfloat_propagateNaNF128UI(uint_fast64_t uiA64, uint_fast64_t uiA0, uint_fast64_t uiB64, uint_fast64_t uiB0);
|
||||
|
||||
#else
|
||||
|
||||
|
@ -315,7 +313,9 @@ struct uint128
|
|||
| common NaN at the location pointed to by 'zPtr'. If the NaN is a signaling
|
||||
| NaN, the invalid exception is raised.
|
||||
*----------------------------------------------------------------------------*/
|
||||
#define softfloat_extF80MToCommonNaN( aSPtr, zPtr ) if ( ! ((aSPtr)->signif & UINT64_C( 0x4000000000000000 )) ) softfloat_raiseFlags( softfloat_flag_invalid )
|
||||
#define softfloat_extF80MToCommonNaN(aSPtr, zPtr) \
|
||||
if(!((aSPtr)->signif & UINT64_C(0x4000000000000000))) \
|
||||
softfloat_raiseFlags(softfloat_flag_invalid)
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Converts the common NaN pointed to by 'aPtr' into an 80-bit extended
|
||||
|
@ -324,17 +324,12 @@ struct uint128
|
|||
*----------------------------------------------------------------------------*/
|
||||
#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
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
|
@ -343,12 +338,7 @@ void
|
|||
| at the location pointed to by 'zSPtr'. If either original floating-point
|
||||
| value is a signaling NaN, the invalid exception is raised.
|
||||
*----------------------------------------------------------------------------*/
|
||||
void
|
||||
softfloat_propagateNaNExtF80M(
|
||||
const struct extFloat80M *aSPtr,
|
||||
const struct extFloat80M *bSPtr,
|
||||
struct extFloat80M *zSPtr
|
||||
);
|
||||
void softfloat_propagateNaNExtF80M(const struct extFloat80M* aSPtr, const struct extFloat80M* bSPtr, struct extFloat80M* zSPtr);
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| The bit pattern for a default generated 128-bit floating-point NaN.
|
||||
|
@ -366,7 +356,9 @@ void
|
|||
| four 32-bit elements that concatenate in the platform's normal endian order
|
||||
| to form a 128-bit floating-point value.
|
||||
*----------------------------------------------------------------------------*/
|
||||
#define softfloat_f128MToCommonNaN( aWPtr, zPtr ) if ( ! ((aWPtr)[indexWordHi( 4 )] & UINT64_C( 0x0000800000000000 )) ) softfloat_raiseFlags( softfloat_flag_invalid )
|
||||
#define softfloat_f128MToCommonNaN(aWPtr, zPtr) \
|
||||
if(!((aWPtr)[indexWordHi(4)] & UINT64_C(0x0000800000000000))) \
|
||||
softfloat_raiseFlags(softfloat_flag_invalid)
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Converts the common NaN pointed to by 'aPtr' into a 128-bit floating-point
|
||||
|
@ -376,17 +368,14 @@ void
|
|||
*----------------------------------------------------------------------------*/
|
||||
#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
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
|
@ -397,11 +386,8 @@ void
|
|||
| and 'zWPtr' points to an array of four 32-bit elements that concatenate in
|
||||
| the platform's normal endian order to form a 128-bit floating-point value.
|
||||
*----------------------------------------------------------------------------*/
|
||||
void
|
||||
softfloat_propagateNaNF128M(
|
||||
const uint32_t *aWPtr, const uint32_t *bWPtr, uint32_t *zWPtr );
|
||||
void softfloat_propagateNaNF128M(const uint32_t* aWPtr, const uint32_t* bWPtr, uint32_t* zWPtr);
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -37,10 +37,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#ifndef specialize_h
|
||||
#define specialize_h 1
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "primitiveTypes.h"
|
||||
#include "softfloat.h"
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Default value for 'softfloat_detectTininess'.
|
||||
|
@ -114,8 +114,7 @@ uint_fast16_t softfloat_commonNaNToF16UI( const struct commonNaN *aPtr );
|
|||
| the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a
|
||||
| signaling NaN, the invalid exception is raised.
|
||||
*----------------------------------------------------------------------------*/
|
||||
uint_fast16_t
|
||||
softfloat_propagateNaNF16UI( uint_fast16_t uiA, uint_fast16_t uiB );
|
||||
uint_fast16_t softfloat_propagateNaNF16UI(uint_fast16_t uiA, uint_fast16_t uiB);
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| The bit pattern for a default generated 32-bit floating-point NaN.
|
||||
|
@ -149,8 +148,7 @@ 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.
|
||||
|
@ -162,7 +160,8 @@ uint_fast32_t
|
|||
| 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
|
||||
|
@ -184,8 +183,7 @@ 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.
|
||||
|
@ -199,7 +197,8 @@ uint_fast64_t
|
|||
| floating-point signaling NaN.
|
||||
| Note: This macro evaluates its arguments more than once.
|
||||
*----------------------------------------------------------------------------*/
|
||||
#define softfloat_isSigNaNExtF80UI( uiA64, uiA0 ) ((((uiA64) & 0x7FFF) == 0x7FFF) && ! ((uiA0) & UINT64_C( 0x4000000000000000 )) && ((uiA0) & UINT64_C( 0x3FFFFFFFFFFFFFFF )))
|
||||
#define softfloat_isSigNaNExtF80UI(uiA64, uiA0) \
|
||||
((((uiA64)&0x7FFF) == 0x7FFF) && !((uiA0)&UINT64_C(0x4000000000000000)) && ((uiA0)&UINT64_C(0x3FFFFFFFFFFFFFFF)))
|
||||
|
||||
#ifdef SOFTFLOAT_FAST_INT64
|
||||
|
||||
|
@ -215,9 +214,7 @@ uint_fast64_t
|
|||
| location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid
|
||||
| exception is raised.
|
||||
*----------------------------------------------------------------------------*/
|
||||
void
|
||||
softfloat_extF80UIToCommonNaN(
|
||||
uint_fast16_t uiA64, uint_fast64_t uiA0, struct commonNaN *zPtr );
|
||||
void softfloat_extF80UIToCommonNaN(uint_fast16_t uiA64, uint_fast64_t uiA0, struct commonNaN* zPtr);
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Converts the common NaN pointed to by 'aPtr' into an 80-bit extended
|
||||
|
@ -235,13 +232,7 @@ 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.
|
||||
|
@ -255,7 +246,8 @@ struct uint128
|
|||
| point signaling NaN.
|
||||
| Note: This macro evaluates its arguments more than once.
|
||||
*----------------------------------------------------------------------------*/
|
||||
#define softfloat_isSigNaNF128UI( uiA64, uiA0 ) ((((uiA64) & UINT64_C( 0x7FFF800000000000 )) == UINT64_C( 0x7FFF000000000000 )) && ((uiA0) || ((uiA64) & UINT64_C( 0x00007FFFFFFFFFFF ))))
|
||||
#define softfloat_isSigNaNF128UI(uiA64, uiA0) \
|
||||
((((uiA64)&UINT64_C(0x7FFF800000000000)) == UINT64_C(0x7FFF000000000000)) && ((uiA0) || ((uiA64)&UINT64_C(0x00007FFFFFFFFFFF))))
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Assuming the unsigned integer formed from concatenating 'uiA64' and 'uiA0'
|
||||
|
@ -264,9 +256,7 @@ struct uint128
|
|||
| pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid exception
|
||||
| is raised.
|
||||
*----------------------------------------------------------------------------*/
|
||||
void
|
||||
softfloat_f128UIToCommonNaN(
|
||||
uint_fast64_t uiA64, uint_fast64_t uiA0, struct commonNaN *zPtr );
|
||||
void softfloat_f128UIToCommonNaN(uint_fast64_t uiA64, uint_fast64_t uiA0, struct commonNaN* zPtr);
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Converts the common NaN pointed to by 'aPtr' into a 128-bit floating-point
|
||||
|
@ -283,13 +273,7 @@ struct uint128 softfloat_commonNaNToF128UI( const struct commonNaN * );
|
|||
| If either original floating-point value is a signaling NaN, the invalid
|
||||
| exception is raised.
|
||||
*----------------------------------------------------------------------------*/
|
||||
struct uint128
|
||||
softfloat_propagateNaNF128UI(
|
||||
uint_fast64_t uiA64,
|
||||
uint_fast64_t uiA0,
|
||||
uint_fast64_t uiB64,
|
||||
uint_fast64_t uiB0
|
||||
);
|
||||
struct uint128 softfloat_propagateNaNF128UI(uint_fast64_t uiA64, uint_fast64_t uiA0, uint_fast64_t uiB64, uint_fast64_t uiB0);
|
||||
|
||||
#else
|
||||
|
||||
|
@ -304,18 +288,14 @@ struct uint128
|
|||
| common NaN at the location pointed to by 'zPtr'. If the NaN is a signaling
|
||||
| NaN, the invalid exception is raised.
|
||||
*----------------------------------------------------------------------------*/
|
||||
void
|
||||
softfloat_extF80MToCommonNaN(
|
||||
const struct extFloat80M *aSPtr, struct commonNaN *zPtr );
|
||||
void softfloat_extF80MToCommonNaN(const struct extFloat80M* aSPtr, struct commonNaN* zPtr);
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Converts the common NaN pointed to by 'aPtr' into an 80-bit extended
|
||||
| floating-point NaN, and stores this NaN at the location pointed to by
|
||||
| 'zSPtr'.
|
||||
*----------------------------------------------------------------------------*/
|
||||
void
|
||||
softfloat_commonNaNToExtF80M(
|
||||
const struct commonNaN *aPtr, struct extFloat80M *zSPtr );
|
||||
void softfloat_commonNaNToExtF80M(const struct commonNaN* aPtr, struct extFloat80M* zSPtr);
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Assuming at least one of the two 80-bit extended floating-point values
|
||||
|
@ -323,12 +303,7 @@ void
|
|||
| at the location pointed to by 'zSPtr'. If either original floating-point
|
||||
| value is a signaling NaN, the invalid exception is raised.
|
||||
*----------------------------------------------------------------------------*/
|
||||
void
|
||||
softfloat_propagateNaNExtF80M(
|
||||
const struct extFloat80M *aSPtr,
|
||||
const struct extFloat80M *bSPtr,
|
||||
struct extFloat80M *zSPtr
|
||||
);
|
||||
void softfloat_propagateNaNExtF80M(const struct extFloat80M* aSPtr, const struct extFloat80M* bSPtr, struct extFloat80M* zSPtr);
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| The bit pattern for a default generated 128-bit floating-point NaN.
|
||||
|
@ -346,8 +321,7 @@ void
|
|||
| four 32-bit elements that concatenate in the platform's normal endian order
|
||||
| to form a 128-bit floating-point value.
|
||||
*----------------------------------------------------------------------------*/
|
||||
void
|
||||
softfloat_f128MToCommonNaN( const uint32_t *aWPtr, struct commonNaN *zPtr );
|
||||
void softfloat_f128MToCommonNaN(const uint32_t* aWPtr, struct commonNaN* zPtr);
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Converts the common NaN pointed to by 'aPtr' into a 128-bit floating-point
|
||||
|
@ -355,8 +329,7 @@ void
|
|||
| 'zWPtr' points to an array of four 32-bit elements that concatenate in the
|
||||
| platform's normal endian order to form a 128-bit floating-point value.
|
||||
*----------------------------------------------------------------------------*/
|
||||
void
|
||||
softfloat_commonNaNToF128M( const struct commonNaN *aPtr, uint32_t *zWPtr );
|
||||
void softfloat_commonNaNToF128M(const struct commonNaN* aPtr, uint32_t* zWPtr);
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Assuming at least one of the two 128-bit floating-point values pointed to by
|
||||
|
@ -366,11 +339,8 @@ void
|
|||
| and 'zWPtr' points to an array of four 32-bit elements that concatenate in
|
||||
| the platform's normal endian order to form a 128-bit floating-point value.
|
||||
*----------------------------------------------------------------------------*/
|
||||
void
|
||||
softfloat_propagateNaNF128M(
|
||||
const uint32_t *aWPtr, const uint32_t *bWPtr, uint32_t *zWPtr );
|
||||
void softfloat_propagateNaNF128M(const uint32_t* aWPtr, const uint32_t* bWPtr, uint32_t* zWPtr);
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -37,10 +37,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#ifndef specialize_h
|
||||
#define specialize_h 1
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "primitiveTypes.h"
|
||||
#include "softfloat.h"
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Default value for 'softfloat_detectTininess'.
|
||||
|
@ -114,8 +114,7 @@ uint_fast16_t softfloat_commonNaNToF16UI( const struct commonNaN *aPtr );
|
|||
| the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a
|
||||
| signaling NaN, the invalid exception is raised.
|
||||
*----------------------------------------------------------------------------*/
|
||||
uint_fast16_t
|
||||
softfloat_propagateNaNF16UI( uint_fast16_t uiA, uint_fast16_t uiB );
|
||||
uint_fast16_t softfloat_propagateNaNF16UI(uint_fast16_t uiA, uint_fast16_t uiB);
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| The bit pattern for a default generated 32-bit floating-point NaN.
|
||||
|
@ -149,8 +148,7 @@ 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.
|
||||
|
@ -162,7 +160,8 @@ uint_fast32_t
|
|||
| 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
|
||||
|
@ -184,8 +183,7 @@ 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.
|
||||
|
@ -199,7 +197,8 @@ uint_fast64_t
|
|||
| floating-point signaling NaN.
|
||||
| Note: This macro evaluates its arguments more than once.
|
||||
*----------------------------------------------------------------------------*/
|
||||
#define softfloat_isSigNaNExtF80UI( uiA64, uiA0 ) ((((uiA64) & 0x7FFF) == 0x7FFF) && ! ((uiA0) & UINT64_C( 0x4000000000000000 )) && ((uiA0) & UINT64_C( 0x3FFFFFFFFFFFFFFF )))
|
||||
#define softfloat_isSigNaNExtF80UI(uiA64, uiA0) \
|
||||
((((uiA64)&0x7FFF) == 0x7FFF) && !((uiA0)&UINT64_C(0x4000000000000000)) && ((uiA0)&UINT64_C(0x3FFFFFFFFFFFFFFF)))
|
||||
|
||||
#ifdef SOFTFLOAT_FAST_INT64
|
||||
|
||||
|
@ -215,9 +214,7 @@ uint_fast64_t
|
|||
| location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid
|
||||
| exception is raised.
|
||||
*----------------------------------------------------------------------------*/
|
||||
void
|
||||
softfloat_extF80UIToCommonNaN(
|
||||
uint_fast16_t uiA64, uint_fast64_t uiA0, struct commonNaN *zPtr );
|
||||
void softfloat_extF80UIToCommonNaN(uint_fast16_t uiA64, uint_fast64_t uiA0, struct commonNaN* zPtr);
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Converts the common NaN pointed to by 'aPtr' into an 80-bit extended
|
||||
|
@ -235,13 +232,7 @@ 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.
|
||||
|
@ -255,7 +246,8 @@ struct uint128
|
|||
| point signaling NaN.
|
||||
| Note: This macro evaluates its arguments more than once.
|
||||
*----------------------------------------------------------------------------*/
|
||||
#define softfloat_isSigNaNF128UI( uiA64, uiA0 ) ((((uiA64) & UINT64_C( 0x7FFF800000000000 )) == UINT64_C( 0x7FFF000000000000 )) && ((uiA0) || ((uiA64) & UINT64_C( 0x00007FFFFFFFFFFF ))))
|
||||
#define softfloat_isSigNaNF128UI(uiA64, uiA0) \
|
||||
((((uiA64)&UINT64_C(0x7FFF800000000000)) == UINT64_C(0x7FFF000000000000)) && ((uiA0) || ((uiA64)&UINT64_C(0x00007FFFFFFFFFFF))))
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Assuming the unsigned integer formed from concatenating 'uiA64' and 'uiA0'
|
||||
|
@ -264,9 +256,7 @@ struct uint128
|
|||
| pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid exception
|
||||
| is raised.
|
||||
*----------------------------------------------------------------------------*/
|
||||
void
|
||||
softfloat_f128UIToCommonNaN(
|
||||
uint_fast64_t uiA64, uint_fast64_t uiA0, struct commonNaN *zPtr );
|
||||
void softfloat_f128UIToCommonNaN(uint_fast64_t uiA64, uint_fast64_t uiA0, struct commonNaN* zPtr);
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Converts the common NaN pointed to by 'aPtr' into a 128-bit floating-point
|
||||
|
@ -283,13 +273,7 @@ struct uint128 softfloat_commonNaNToF128UI( const struct commonNaN * );
|
|||
| If either original floating-point value is a signaling NaN, the invalid
|
||||
| exception is raised.
|
||||
*----------------------------------------------------------------------------*/
|
||||
struct uint128
|
||||
softfloat_propagateNaNF128UI(
|
||||
uint_fast64_t uiA64,
|
||||
uint_fast64_t uiA0,
|
||||
uint_fast64_t uiB64,
|
||||
uint_fast64_t uiB0
|
||||
);
|
||||
struct uint128 softfloat_propagateNaNF128UI(uint_fast64_t uiA64, uint_fast64_t uiA0, uint_fast64_t uiB64, uint_fast64_t uiB0);
|
||||
|
||||
#else
|
||||
|
||||
|
@ -304,18 +288,14 @@ struct uint128
|
|||
| common NaN at the location pointed to by 'zPtr'. If the NaN is a signaling
|
||||
| NaN, the invalid exception is raised.
|
||||
*----------------------------------------------------------------------------*/
|
||||
void
|
||||
softfloat_extF80MToCommonNaN(
|
||||
const struct extFloat80M *aSPtr, struct commonNaN *zPtr );
|
||||
void softfloat_extF80MToCommonNaN(const struct extFloat80M* aSPtr, struct commonNaN* zPtr);
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Converts the common NaN pointed to by 'aPtr' into an 80-bit extended
|
||||
| floating-point NaN, and stores this NaN at the location pointed to by
|
||||
| 'zSPtr'.
|
||||
*----------------------------------------------------------------------------*/
|
||||
void
|
||||
softfloat_commonNaNToExtF80M(
|
||||
const struct commonNaN *aPtr, struct extFloat80M *zSPtr );
|
||||
void softfloat_commonNaNToExtF80M(const struct commonNaN* aPtr, struct extFloat80M* zSPtr);
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Assuming at least one of the two 80-bit extended floating-point values
|
||||
|
@ -323,12 +303,7 @@ void
|
|||
| at the location pointed to by 'zSPtr'. If either original floating-point
|
||||
| value is a signaling NaN, the invalid exception is raised.
|
||||
*----------------------------------------------------------------------------*/
|
||||
void
|
||||
softfloat_propagateNaNExtF80M(
|
||||
const struct extFloat80M *aSPtr,
|
||||
const struct extFloat80M *bSPtr,
|
||||
struct extFloat80M *zSPtr
|
||||
);
|
||||
void softfloat_propagateNaNExtF80M(const struct extFloat80M* aSPtr, const struct extFloat80M* bSPtr, struct extFloat80M* zSPtr);
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| The bit pattern for a default generated 128-bit floating-point NaN.
|
||||
|
@ -346,8 +321,7 @@ void
|
|||
| four 32-bit elements that concatenate in the platform's normal endian order
|
||||
| to form a 128-bit floating-point value.
|
||||
*----------------------------------------------------------------------------*/
|
||||
void
|
||||
softfloat_f128MToCommonNaN( const uint32_t *aWPtr, struct commonNaN *zPtr );
|
||||
void softfloat_f128MToCommonNaN(const uint32_t* aWPtr, struct commonNaN* zPtr);
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Converts the common NaN pointed to by 'aPtr' into a 128-bit floating-point
|
||||
|
@ -355,8 +329,7 @@ void
|
|||
| 'zWPtr' points to an array of four 32-bit elements that concatenate in the
|
||||
| platform's normal endian order to form a 128-bit floating-point value.
|
||||
*----------------------------------------------------------------------------*/
|
||||
void
|
||||
softfloat_commonNaNToF128M( const struct commonNaN *aPtr, uint32_t *zWPtr );
|
||||
void softfloat_commonNaNToF128M(const struct commonNaN* aPtr, uint32_t* zWPtr);
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Assuming at least one of the two 128-bit floating-point values pointed to by
|
||||
|
@ -366,11 +339,8 @@ void
|
|||
| and 'zWPtr' points to an array of four 32-bit elements that concatenate in
|
||||
| the platform's normal endian order to form a 128-bit floating-point value.
|
||||
*----------------------------------------------------------------------------*/
|
||||
void
|
||||
softfloat_propagateNaNF128M(
|
||||
const uint32_t *aWPtr, const uint32_t *bWPtr, uint32_t *zWPtr );
|
||||
void softfloat_propagateNaNF128M(const uint32_t* aWPtr, const uint32_t* bWPtr, uint32_t* zWPtr);
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -37,33 +37,43 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#ifndef internals_h
|
||||
#define internals_h 1
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "primitives.h"
|
||||
#include "softfloat_types.h"
|
||||
#include <stdbool.h>
|
||||
#include <stdint.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
|
||||
|
@ -71,9 +81,7 @@ 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
|
||||
|
@ -87,7 +95,10 @@ 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);
|
||||
|
@ -95,9 +106,7 @@ 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);
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
@ -108,7 +117,10 @@ float16_t
|
|||
|
||||
#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);
|
||||
|
@ -116,9 +128,7 @@ 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);
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
@ -129,7 +139,10 @@ float32_t
|
|||
|
||||
#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);
|
||||
|
@ -137,9 +150,7 @@ 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);
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
@ -154,22 +165,17 @@ float64_t
|
|||
/*----------------------------------------------------------------------------
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
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);
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
@ -180,67 +186,35 @@ extFloat80_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*);
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
@ -251,9 +225,7 @@ int
|
|||
|
||||
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*);
|
||||
|
@ -261,18 +233,9 @@ 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
|
||||
|
||||
|
|
|
@ -39,57 +39,57 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
#ifdef INLINE
|
||||
|
||||
#include <stdint.h>
|
||||
#include "primitiveTypes.h"
|
||||
#include <stdint.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,4 +111,3 @@ void
|
|||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -42,13 +42,27 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#ifdef SOFTFLOAT_FAST_INT64
|
||||
|
||||
#ifdef LITTLEENDIAN
|
||||
struct uint128 { uint64_t v0, v64; };
|
||||
struct uint64_extra { uint64_t extra, v; };
|
||||
struct uint128_extra { uint64_t extra; struct uint128 v; };
|
||||
struct uint128 {
|
||||
uint64_t v0, v64;
|
||||
};
|
||||
struct uint64_extra {
|
||||
uint64_t extra, v;
|
||||
};
|
||||
struct uint128_extra {
|
||||
uint64_t extra;
|
||||
struct uint128 v;
|
||||
};
|
||||
#else
|
||||
struct uint128 { uint64_t v64, v0; };
|
||||
struct uint64_extra { uint64_t v, extra; };
|
||||
struct uint128_extra { struct uint128 v; uint64_t extra; };
|
||||
struct uint128 {
|
||||
uint64_t v64, v0;
|
||||
};
|
||||
struct uint64_extra {
|
||||
uint64_t v, extra;
|
||||
};
|
||||
struct uint128_extra {
|
||||
struct uint128 v;
|
||||
uint64_t extra;
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -67,7 +81,8 @@ struct uint128_extra { struct uint128 v; uint64_t 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))
|
||||
|
@ -78,8 +93,8 @@ struct uint128_extra { struct uint128 v; uint64_t 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
|
||||
|
||||
|
|
|
@ -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,8 +50,7 @@ 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
|
||||
|
@ -68,10 +67,8 @@ 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);
|
||||
|
@ -89,10 +86,8 @@ 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);
|
||||
|
@ -112,8 +107,7 @@ 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;
|
||||
|
@ -133,8 +127,7 @@ 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;
|
||||
|
@ -222,8 +215,7 @@ 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
|
||||
|
@ -237,8 +229,7 @@ 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
|
||||
|
@ -252,8 +243,7 @@ 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
|
||||
|
@ -266,17 +256,14 @@ bool softfloat_lt128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 );
|
|||
*----------------------------------------------------------------------------*/
|
||||
#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
|
||||
INLINE
|
||||
struct uint128
|
||||
softfloat_shortShiftLeft128( uint64_t a64, uint64_t a0, uint_fast8_t dist )
|
||||
{
|
||||
struct uint128 softfloat_shortShiftLeft128(uint64_t a64, uint64_t a0, uint_fast8_t dist) {
|
||||
struct uint128 z;
|
||||
z.v64 = a64 << dist | a0 >> (-dist & 63);
|
||||
z.v0 = a0 << dist;
|
||||
return z;
|
||||
}
|
||||
#else
|
||||
struct uint128
|
||||
softfloat_shortShiftLeft128( uint64_t a64, uint64_t a0, uint_fast8_t dist );
|
||||
struct uint128 softfloat_shortShiftLeft128(uint64_t a64, uint64_t a0, uint_fast8_t dist);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
@ -287,17 +274,14 @@ struct uint128
|
|||
*----------------------------------------------------------------------------*/
|
||||
#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
|
||||
INLINE
|
||||
struct uint128
|
||||
softfloat_shortShiftRight128( uint64_t a64, uint64_t a0, uint_fast8_t dist )
|
||||
{
|
||||
struct uint128 softfloat_shortShiftRight128(uint64_t a64, uint64_t a0, uint_fast8_t dist) {
|
||||
struct uint128 z;
|
||||
z.v64 = a64 >> dist;
|
||||
z.v0 = a64 << (-dist & 63) | a0 >> dist;
|
||||
return z;
|
||||
}
|
||||
#else
|
||||
struct uint128
|
||||
softfloat_shortShiftRight128( uint64_t a64, uint64_t a0, uint_fast8_t dist );
|
||||
struct uint128 softfloat_shortShiftRight128(uint64_t a64, uint64_t a0, uint_fast8_t dist);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
@ -308,19 +292,14 @@ struct uint128
|
|||
*----------------------------------------------------------------------------*/
|
||||
#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
|
||||
INLINE
|
||||
struct uint64_extra
|
||||
softfloat_shortShiftRightJam64Extra(
|
||||
uint64_t a, uint64_t extra, uint_fast8_t dist )
|
||||
{
|
||||
struct uint64_extra softfloat_shortShiftRightJam64Extra(uint64_t a, uint64_t extra, uint_fast8_t dist) {
|
||||
struct uint64_extra z;
|
||||
z.v = a >> dist;
|
||||
z.extra = a << (-dist & 63) | (extra != 0);
|
||||
return z;
|
||||
}
|
||||
#else
|
||||
struct uint64_extra
|
||||
softfloat_shortShiftRightJam64Extra(
|
||||
uint64_t a, uint64_t extra, uint_fast8_t dist );
|
||||
struct uint64_extra softfloat_shortShiftRightJam64Extra(uint64_t a, uint64_t extra, uint_fast8_t dist);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
@ -334,22 +313,15 @@ struct uint64_extra
|
|||
*----------------------------------------------------------------------------*/
|
||||
#if defined INLINE_LEVEL && (3 <= INLINE_LEVEL)
|
||||
INLINE
|
||||
struct uint128
|
||||
softfloat_shortShiftRightJam128(
|
||||
uint64_t a64, uint64_t a0, uint_fast8_t dist )
|
||||
{
|
||||
struct uint128 softfloat_shortShiftRightJam128(uint64_t a64, uint64_t a0, uint_fast8_t dist) {
|
||||
uint_fast8_t negDist = -dist;
|
||||
struct uint128 z;
|
||||
z.v64 = a64 >> dist;
|
||||
z.v0 =
|
||||
a64<<(negDist & 63) | a0>>dist
|
||||
| ((uint64_t) (a0<<(negDist & 63)) != 0);
|
||||
z.v0 = a64 << (negDist & 63) | a0 >> dist | ((uint64_t)(a0 << (negDist & 63)) != 0);
|
||||
return z;
|
||||
}
|
||||
#else
|
||||
struct uint128
|
||||
softfloat_shortShiftRightJam128(
|
||||
uint64_t a64, uint64_t a0, uint_fast8_t dist );
|
||||
struct uint128 softfloat_shortShiftRightJam128(uint64_t a64, uint64_t a0, uint_fast8_t dist);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
@ -360,10 +332,7 @@ struct uint128
|
|||
*----------------------------------------------------------------------------*/
|
||||
#if defined INLINE_LEVEL && (3 <= INLINE_LEVEL)
|
||||
INLINE
|
||||
struct uint128_extra
|
||||
softfloat_shortShiftRightJam128Extra(
|
||||
uint64_t a64, uint64_t a0, uint64_t extra, uint_fast8_t dist )
|
||||
{
|
||||
struct uint128_extra softfloat_shortShiftRightJam128Extra(uint64_t a64, uint64_t a0, uint64_t extra, uint_fast8_t dist) {
|
||||
uint_fast8_t negDist = -dist;
|
||||
struct uint128_extra z;
|
||||
z.v.v64 = a64 >> dist;
|
||||
|
@ -372,9 +341,7 @@ struct uint128_extra
|
|||
return z;
|
||||
}
|
||||
#else
|
||||
struct uint128_extra
|
||||
softfloat_shortShiftRightJam128Extra(
|
||||
uint64_t a64, uint64_t a0, uint64_t extra, uint_fast8_t dist );
|
||||
struct uint128_extra softfloat_shortShiftRightJam128Extra(uint64_t a64, uint64_t a0, uint64_t extra, uint_fast8_t dist);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
@ -397,10 +364,7 @@ struct uint128_extra
|
|||
*----------------------------------------------------------------------------*/
|
||||
#if defined INLINE_LEVEL && (4 <= INLINE_LEVEL)
|
||||
INLINE
|
||||
struct uint64_extra
|
||||
softfloat_shiftRightJam64Extra(
|
||||
uint64_t a, uint64_t extra, uint_fast32_t dist )
|
||||
{
|
||||
struct uint64_extra softfloat_shiftRightJam64Extra(uint64_t a, uint64_t extra, uint_fast32_t dist) {
|
||||
struct uint64_extra z;
|
||||
if(dist < 64) {
|
||||
z.v = a >> dist;
|
||||
|
@ -413,9 +377,7 @@ struct uint64_extra
|
|||
return z;
|
||||
}
|
||||
#else
|
||||
struct uint64_extra
|
||||
softfloat_shiftRightJam64Extra(
|
||||
uint64_t a, uint64_t extra, uint_fast32_t dist );
|
||||
struct uint64_extra softfloat_shiftRightJam64Extra(uint64_t a, uint64_t extra, uint_fast32_t dist);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
@ -430,8 +392,7 @@ struct uint64_extra
|
|||
| greater than 128, the result will be either 0 or 1, depending on whether the
|
||||
| original 128 bits are all zeros.
|
||||
*----------------------------------------------------------------------------*/
|
||||
struct uint128
|
||||
softfloat_shiftRightJam128( uint64_t a64, uint64_t a0, uint_fast32_t dist );
|
||||
struct uint128 softfloat_shiftRightJam128(uint64_t a64, uint64_t a0, uint_fast32_t dist);
|
||||
#endif
|
||||
|
||||
#ifndef softfloat_shiftRightJam128Extra
|
||||
|
@ -452,9 +413,7 @@ struct uint128
|
|||
| is modified as described above and returned in the 'extra' field of the
|
||||
| result.)
|
||||
*----------------------------------------------------------------------------*/
|
||||
struct uint128_extra
|
||||
softfloat_shiftRightJam128Extra(
|
||||
uint64_t a64, uint64_t a0, uint64_t extra, uint_fast32_t dist );
|
||||
struct uint128_extra softfloat_shiftRightJam128Extra(uint64_t a64, uint64_t a0, uint64_t extra, uint_fast32_t dist);
|
||||
#endif
|
||||
|
||||
#ifndef softfloat_shiftRightJam256M
|
||||
|
@ -470,9 +429,7 @@ struct uint128_extra
|
|||
| is greater than 256, the stored result will be either 0 or 1, depending on
|
||||
| whether the original 256 bits are all zeros.
|
||||
*----------------------------------------------------------------------------*/
|
||||
void
|
||||
softfloat_shiftRightJam256M(
|
||||
const uint64_t *aPtr, uint_fast32_t dist, uint64_t *zPtr );
|
||||
void softfloat_shiftRightJam256M(const uint64_t* aPtr, uint_fast32_t dist, uint64_t* zPtr);
|
||||
#endif
|
||||
|
||||
#ifndef softfloat_add128
|
||||
|
@ -483,17 +440,14 @@ void
|
|||
*----------------------------------------------------------------------------*/
|
||||
#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
|
||||
INLINE
|
||||
struct uint128
|
||||
softfloat_add128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 )
|
||||
{
|
||||
struct uint128 softfloat_add128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0) {
|
||||
struct uint128 z;
|
||||
z.v0 = a0 + b0;
|
||||
z.v64 = a64 + b64 + (z.v0 < a0);
|
||||
return z;
|
||||
}
|
||||
#else
|
||||
struct uint128
|
||||
softfloat_add128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 );
|
||||
struct uint128 softfloat_add128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
@ -505,9 +459,7 @@ struct uint128
|
|||
| an array of four 64-bit elements that concatenate in the platform's normal
|
||||
| endian order to form a 256-bit integer.
|
||||
*----------------------------------------------------------------------------*/
|
||||
void
|
||||
softfloat_add256M(
|
||||
const uint64_t *aPtr, const uint64_t *bPtr, uint64_t *zPtr );
|
||||
void softfloat_add256M(const uint64_t* aPtr, const uint64_t* bPtr, uint64_t* zPtr);
|
||||
#endif
|
||||
|
||||
#ifndef softfloat_sub128
|
||||
|
@ -518,9 +470,7 @@ void
|
|||
*----------------------------------------------------------------------------*/
|
||||
#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
|
||||
INLINE
|
||||
struct uint128
|
||||
softfloat_sub128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 )
|
||||
{
|
||||
struct uint128 softfloat_sub128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0) {
|
||||
struct uint128 z;
|
||||
z.v0 = a0 - b0;
|
||||
z.v64 = a64 - b64;
|
||||
|
@ -528,8 +478,7 @@ struct uint128
|
|||
return z;
|
||||
}
|
||||
#else
|
||||
struct uint128
|
||||
softfloat_sub128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 );
|
||||
struct uint128 softfloat_sub128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
@ -542,9 +491,7 @@ struct uint128
|
|||
| 64-bit elements that concatenate in the platform's normal endian order to
|
||||
| form a 256-bit integer.
|
||||
*----------------------------------------------------------------------------*/
|
||||
void
|
||||
softfloat_sub256M(
|
||||
const uint64_t *aPtr, const uint64_t *bPtr, uint64_t *zPtr );
|
||||
void softfloat_sub256M(const uint64_t* aPtr, const uint64_t* bPtr, uint64_t* zPtr);
|
||||
#endif
|
||||
|
||||
#ifndef softfloat_mul64ByShifted32To128
|
||||
|
@ -552,8 +499,7 @@ void
|
|||
| Returns the 128-bit product of 'a', 'b', and 2^32.
|
||||
*----------------------------------------------------------------------------*/
|
||||
#if defined INLINE_LEVEL && (3 <= INLINE_LEVEL)
|
||||
INLINE struct uint128 softfloat_mul64ByShifted32To128( uint64_t a, uint32_t b )
|
||||
{
|
||||
INLINE struct uint128 softfloat_mul64ByShifted32To128(uint64_t a, uint32_t b) {
|
||||
uint_fast64_t mid;
|
||||
struct uint128 z;
|
||||
mid = (uint_fast64_t)(uint32_t)a * b;
|
||||
|
@ -581,8 +527,7 @@ 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;
|
||||
|
@ -605,9 +550,7 @@ struct uint128 softfloat_mul128By32( uint64_t a64, uint64_t a0, uint32_t b );
|
|||
| Argument 'zPtr' points to an array of four 64-bit elements that concatenate
|
||||
| in the platform's normal endian order to form a 256-bit integer.
|
||||
*----------------------------------------------------------------------------*/
|
||||
void
|
||||
softfloat_mul128To256M(
|
||||
uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0, uint64_t *zPtr );
|
||||
void softfloat_mul128To256M(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0, uint64_t* zPtr);
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
@ -638,8 +581,7 @@ int_fast8_t softfloat_compare96M( const uint32_t *aPtr, const uint32_t *bPtr );
|
|||
| Each of 'aPtr' and 'bPtr' points to an array of four 32-bit elements that
|
||||
| concatenate in the platform's normal endian order to form a 128-bit integer.
|
||||
*----------------------------------------------------------------------------*/
|
||||
int_fast8_t
|
||||
softfloat_compare128M( const uint32_t *aPtr, const uint32_t *bPtr );
|
||||
int_fast8_t softfloat_compare128M(const uint32_t* aPtr, const uint32_t* bPtr);
|
||||
#endif
|
||||
|
||||
#ifndef softfloat_shortShiftLeft64To96M
|
||||
|
@ -652,19 +594,14 @@ int_fast8_t
|
|||
*----------------------------------------------------------------------------*/
|
||||
#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
|
||||
INLINE
|
||||
void
|
||||
softfloat_shortShiftLeft64To96M(
|
||||
uint64_t a, uint_fast8_t dist, uint32_t *zPtr )
|
||||
{
|
||||
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
|
||||
|
||||
|
@ -678,13 +615,7 @@ void
|
|||
| that concatenate in the platform's normal endian order to form an N-bit
|
||||
| integer.
|
||||
*----------------------------------------------------------------------------*/
|
||||
void
|
||||
softfloat_shortShiftLeftM(
|
||||
uint_fast8_t size_words,
|
||||
const uint32_t *aPtr,
|
||||
uint_fast8_t dist,
|
||||
uint32_t *zPtr
|
||||
);
|
||||
void softfloat_shortShiftLeftM(uint_fast8_t size_words, const uint32_t* aPtr, uint_fast8_t dist, uint32_t* zPtr);
|
||||
#endif
|
||||
|
||||
#ifndef softfloat_shortShiftLeft96M
|
||||
|
@ -722,13 +653,7 @@ void
|
|||
| The value of 'dist' can be arbitrarily large. In particular, if 'dist' is
|
||||
| greater than N, the stored result will be 0.
|
||||
*----------------------------------------------------------------------------*/
|
||||
void
|
||||
softfloat_shiftLeftM(
|
||||
uint_fast8_t size_words,
|
||||
const uint32_t *aPtr,
|
||||
uint32_t dist,
|
||||
uint32_t *zPtr
|
||||
);
|
||||
void softfloat_shiftLeftM(uint_fast8_t size_words, const uint32_t* aPtr, uint32_t dist, uint32_t* zPtr);
|
||||
#endif
|
||||
|
||||
#ifndef softfloat_shiftLeft96M
|
||||
|
@ -765,13 +690,7 @@ void
|
|||
| that concatenate in the platform's normal endian order to form an N-bit
|
||||
| integer.
|
||||
*----------------------------------------------------------------------------*/
|
||||
void
|
||||
softfloat_shortShiftRightM(
|
||||
uint_fast8_t size_words,
|
||||
const uint32_t *aPtr,
|
||||
uint_fast8_t dist,
|
||||
uint32_t *zPtr
|
||||
);
|
||||
void softfloat_shortShiftRightM(uint_fast8_t size_words, const uint32_t* aPtr, uint_fast8_t dist, uint32_t* zPtr);
|
||||
#endif
|
||||
|
||||
#ifndef softfloat_shortShiftRight128M
|
||||
|
@ -801,9 +720,7 @@ void
|
|||
| to a 'size_words'-long array of 32-bit elements that concatenate in the
|
||||
| platform's normal endian order to form an N-bit integer.
|
||||
*----------------------------------------------------------------------------*/
|
||||
void
|
||||
softfloat_shortShiftRightJamM(
|
||||
uint_fast8_t, const uint32_t *, uint_fast8_t, uint32_t * );
|
||||
void softfloat_shortShiftRightJamM(uint_fast8_t, const uint32_t*, uint_fast8_t, uint32_t*);
|
||||
#endif
|
||||
|
||||
#ifndef softfloat_shortShiftRightJam160M
|
||||
|
@ -825,13 +742,7 @@ void
|
|||
| The value of 'dist' can be arbitrarily large. In particular, if 'dist' is
|
||||
| greater than N, the stored result will be 0.
|
||||
*----------------------------------------------------------------------------*/
|
||||
void
|
||||
softfloat_shiftRightM(
|
||||
uint_fast8_t size_words,
|
||||
const uint32_t *aPtr,
|
||||
uint32_t dist,
|
||||
uint32_t *zPtr
|
||||
);
|
||||
void softfloat_shiftRightM(uint_fast8_t size_words, const uint32_t* aPtr, uint32_t dist, uint32_t* zPtr);
|
||||
#endif
|
||||
|
||||
#ifndef softfloat_shiftRight96M
|
||||
|
@ -856,13 +767,7 @@ void
|
|||
| is greater than N, the stored result will be either 0 or 1, depending on
|
||||
| whether the original N bits are all zeros.
|
||||
*----------------------------------------------------------------------------*/
|
||||
void
|
||||
softfloat_shiftRightJamM(
|
||||
uint_fast8_t size_words,
|
||||
const uint32_t *aPtr,
|
||||
uint32_t dist,
|
||||
uint32_t *zPtr
|
||||
);
|
||||
void softfloat_shiftRightJamM(uint_fast8_t size_words, const uint32_t* aPtr, uint32_t dist, uint32_t* zPtr);
|
||||
#endif
|
||||
|
||||
#ifndef softfloat_shiftRightJam96M
|
||||
|
@ -898,13 +803,7 @@ void
|
|||
| elements that concatenate in the platform's normal endian order to form an
|
||||
| N-bit integer.
|
||||
*----------------------------------------------------------------------------*/
|
||||
void
|
||||
softfloat_addM(
|
||||
uint_fast8_t size_words,
|
||||
const uint32_t *aPtr,
|
||||
const uint32_t *bPtr,
|
||||
uint32_t *zPtr
|
||||
);
|
||||
void softfloat_addM(uint_fast8_t size_words, const uint32_t* aPtr, const uint32_t* bPtr, uint32_t* zPtr);
|
||||
#endif
|
||||
|
||||
#ifndef softfloat_add96M
|
||||
|
@ -940,14 +839,7 @@ void
|
|||
| points to a 'size_words'-long array of 32-bit elements that concatenate in
|
||||
| the platform's normal endian order to form an N-bit integer.
|
||||
*----------------------------------------------------------------------------*/
|
||||
uint_fast8_t
|
||||
softfloat_addCarryM(
|
||||
uint_fast8_t size_words,
|
||||
const uint32_t *aPtr,
|
||||
const uint32_t *bPtr,
|
||||
uint_fast8_t carry,
|
||||
uint32_t *zPtr
|
||||
);
|
||||
uint_fast8_t softfloat_addCarryM(uint_fast8_t size_words, const uint32_t* aPtr, const uint32_t* bPtr, uint_fast8_t carry, uint32_t* zPtr);
|
||||
#endif
|
||||
|
||||
#ifndef softfloat_addComplCarryM
|
||||
|
@ -956,14 +848,8 @@ uint_fast8_t
|
|||
| the value of the unsigned integer pointed to by 'bPtr' is bit-wise completed
|
||||
| before the addition.
|
||||
*----------------------------------------------------------------------------*/
|
||||
uint_fast8_t
|
||||
softfloat_addComplCarryM(
|
||||
uint_fast8_t size_words,
|
||||
const uint32_t *aPtr,
|
||||
const uint32_t *bPtr,
|
||||
uint_fast8_t carry,
|
||||
uint32_t *zPtr
|
||||
);
|
||||
uint_fast8_t softfloat_addComplCarryM(uint_fast8_t size_words, const uint32_t* aPtr, const uint32_t* bPtr, uint_fast8_t carry,
|
||||
uint32_t* zPtr);
|
||||
#endif
|
||||
|
||||
#ifndef softfloat_addComplCarry96M
|
||||
|
@ -1052,13 +938,7 @@ void softfloat_sub1XM( uint_fast8_t size_words, uint32_t *zPtr );
|
|||
| array of 32-bit elements that concatenate in the platform's normal endian
|
||||
| order to form an N-bit integer.
|
||||
*----------------------------------------------------------------------------*/
|
||||
void
|
||||
softfloat_subM(
|
||||
uint_fast8_t size_words,
|
||||
const uint32_t *aPtr,
|
||||
const uint32_t *bPtr,
|
||||
uint32_t *zPtr
|
||||
);
|
||||
void softfloat_subM(uint_fast8_t size_words, const uint32_t* aPtr, const uint32_t* bPtr, uint32_t* zPtr);
|
||||
#endif
|
||||
|
||||
#ifndef softfloat_sub96M
|
||||
|
@ -1104,9 +984,7 @@ void softfloat_mul64To128M( uint64_t a, uint64_t b, uint32_t *zPtr );
|
|||
| Argument 'zPtr' points to an array of eight 32-bit elements that concatenate
|
||||
| to form a 256-bit integer.
|
||||
*----------------------------------------------------------------------------*/
|
||||
void
|
||||
softfloat_mul128MTo256M(
|
||||
const uint32_t *aPtr, const uint32_t *bPtr, uint32_t *zPtr );
|
||||
void softfloat_mul128MTo256M(const uint32_t* aPtr, const uint32_t* bPtr, uint32_t* zPtr);
|
||||
#endif
|
||||
|
||||
#ifndef softfloat_remStepMBy32
|
||||
|
@ -1119,15 +997,8 @@ void
|
|||
| to a 'size_words'-long array of 32-bit elements that concatenate in the
|
||||
| platform's normal endian order to form an N-bit integer.
|
||||
*----------------------------------------------------------------------------*/
|
||||
void
|
||||
softfloat_remStepMBy32(
|
||||
uint_fast8_t size_words,
|
||||
const uint32_t *remPtr,
|
||||
uint_fast8_t dist,
|
||||
const uint32_t *bPtr,
|
||||
uint32_t q,
|
||||
uint32_t *zPtr
|
||||
);
|
||||
void softfloat_remStepMBy32(uint_fast8_t size_words, const uint32_t* remPtr, uint_fast8_t dist, const uint32_t* bPtr, uint32_t q,
|
||||
uint32_t* zPtr);
|
||||
#endif
|
||||
|
||||
#ifndef softfloat_remStep96MBy32
|
||||
|
@ -1157,4 +1028,3 @@ void
|
|||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -34,7 +34,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
=============================================================================*/
|
||||
|
||||
|
||||
/*============================================================================
|
||||
| Note: If SoftFloat is made available as a general library for programs to
|
||||
| use, it is strongly recommended that a platform-specific version of this
|
||||
|
@ -42,13 +41,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
| eliminates all dependencies on compile-time macros.
|
||||
*============================================================================*/
|
||||
|
||||
|
||||
#ifndef softfloat_h
|
||||
#define softfloat_h 1
|
||||
|
||||
#include "softfloat_types.h"
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "softfloat_types.h"
|
||||
|
||||
#ifndef THREAD_LOCAL
|
||||
#define THREAD_LOCAL
|
||||
|
@ -58,10 +56,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
| Software floating-point underflow tininess-detection mode.
|
||||
*----------------------------------------------------------------------------*/
|
||||
extern THREAD_LOCAL uint_fast8_t softfloat_detectTininess;
|
||||
enum {
|
||||
softfloat_tininess_beforeRounding = 0,
|
||||
softfloat_tininess_afterRounding = 1
|
||||
};
|
||||
enum { softfloat_tininess_beforeRounding = 0, softfloat_tininess_afterRounding = 1 };
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Software floating-point rounding mode. (Mode "odd" is supported only if
|
||||
|
@ -288,9 +283,7 @@ 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*);
|
||||
|
@ -353,10 +346,7 @@ 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*);
|
||||
|
@ -369,4 +359,3 @@ bool f128M_lt_quiet( const float128_t *, const float128_t * );
|
|||
bool f128M_isSignalingNaN(const float128_t*);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -47,10 +47,18 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
| the types below may, if desired, be defined as aliases for the native types
|
||||
| (typically 'float' and 'double', and possibly 'long double').
|
||||
*----------------------------------------------------------------------------*/
|
||||
typedef struct { uint16_t v; } float16_t;
|
||||
typedef struct { uint32_t v; } float32_t;
|
||||
typedef struct { uint64_t v; } float64_t;
|
||||
typedef struct { uint64_t v[2]; } float128_t;
|
||||
typedef struct {
|
||||
uint16_t v;
|
||||
} float16_t;
|
||||
typedef struct {
|
||||
uint32_t v;
|
||||
} float32_t;
|
||||
typedef struct {
|
||||
uint64_t v;
|
||||
} float64_t;
|
||||
typedef struct {
|
||||
uint64_t v[2];
|
||||
} float128_t;
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| The format of an 80-bit extended floating-point number in memory. This
|
||||
|
@ -58,9 +66,15 @@ typedef struct { uint64_t v[2]; } float128_t;
|
|||
| named 'signif'.
|
||||
*----------------------------------------------------------------------------*/
|
||||
#ifdef LITTLEENDIAN
|
||||
struct extFloat80M { uint64_t signif; uint16_t signExp; };
|
||||
struct extFloat80M {
|
||||
uint64_t signif;
|
||||
uint16_t signExp;
|
||||
};
|
||||
#else
|
||||
struct extFloat80M { uint16_t signExp; uint64_t signif; };
|
||||
struct extFloat80M {
|
||||
uint16_t signExp;
|
||||
uint64_t signif;
|
||||
};
|
||||
#endif
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
|
@ -78,4 +92,3 @@ struct extFloat80M { uint16_t signExp; uint64_t signif; };
|
|||
typedef struct extFloat80M extFloat80_t;
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
/iss
|
||||
/vm
|
||||
/sysc
|
|
@ -35,6 +35,7 @@
|
|||
#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 {
|
||||
|
@ -46,7 +47,7 @@ public:
|
|||
using this_class = hwl<BASE>;
|
||||
using reg_t = typename BASE::reg_t;
|
||||
|
||||
hwl();
|
||||
hwl(feature_config cfg = feature_config{});
|
||||
virtual ~hwl() = default;
|
||||
|
||||
protected:
|
||||
|
@ -54,9 +55,9 @@ protected:
|
|||
iss::status write_custom_csr_reg(unsigned addr, reg_t val) override;
|
||||
};
|
||||
|
||||
|
||||
template <typename BASE>
|
||||
inline hwl<BASE>::hwl() {
|
||||
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);
|
||||
|
@ -67,28 +68,50 @@ inline hwl<BASE>::hwl() {
|
|||
}
|
||||
}
|
||||
|
||||
template<typename BASE>
|
||||
inline iss::status iss::arch::hwl<BASE>::read_custom_csr_reg(unsigned addr, reg_t &val) {
|
||||
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;
|
||||
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) {
|
||||
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;
|
||||
case 0x800:
|
||||
this->reg.lpstart0 = val;
|
||||
break;
|
||||
case 0x801:
|
||||
this->reg.lpend0 = val;
|
||||
break;
|
||||
case 0x802:
|
||||
this->reg.lpcount0 = val;
|
||||
break;
|
||||
case 0x804:
|
||||
this->reg.lpstart1 = val;
|
||||
break;
|
||||
case 0x805:
|
||||
this->reg.lpend1 = val;
|
||||
break;
|
||||
case 0x806:
|
||||
this->reg.lpcount1 = val;
|
||||
break;
|
||||
}
|
||||
return iss::Ok;
|
||||
}
|
||||
|
@ -96,5 +119,4 @@ inline iss::status iss::arch::hwl<BASE>::write_custom_csr_reg(unsigned addr, reg
|
|||
} // namespace arch
|
||||
} // namespace iss
|
||||
|
||||
|
||||
#endif /* _RISCV_HART_M_P_H */
|
|
@ -51,12 +51,18 @@ enum riscv_csr {
|
|||
ustatus = 0x000,
|
||||
uie = 0x004,
|
||||
utvec = 0x005,
|
||||
utvt = 0x007, // CLIC
|
||||
// User Trap Handling
|
||||
uscratch = 0x040,
|
||||
uepc = 0x041,
|
||||
ucause = 0x042,
|
||||
utval = 0x043,
|
||||
uip = 0x044,
|
||||
uxnti = 0x045, // CLIC
|
||||
uintstatus = 0xCB1, // MRW Current interrupt levels (CLIC) - addr subject to change
|
||||
uintthresh = 0x047, // MRW Interrupt-level threshold (CLIC) - addr subject to change
|
||||
uscratchcsw = 0x048, // MRW Conditional scratch swap on priv mode change (CLIC)
|
||||
uscratchcswl = 0x049, // MRW Conditional scratch swap on level change (CLIC)
|
||||
// User Floating-Point CSRs
|
||||
fflags = 0x001,
|
||||
frm = 0x002,
|
||||
|
@ -114,11 +120,10 @@ enum riscv_csr {
|
|||
mtval = 0x343,
|
||||
mip = 0x344,
|
||||
mxnti = 0x345, // CLIC
|
||||
mintstatus = 0x346, // MRW Current interrupt levels (CLIC) - addr subject to change
|
||||
mintstatus = 0xFB1, // MRW Current interrupt levels (CLIC) - addr subject to change
|
||||
mintthresh = 0x347, // MRW Interrupt-level threshold (CLIC) - addr subject to change
|
||||
mscratchcsw = 0x348, // MRW Conditional scratch swap on priv mode change (CLIC)
|
||||
mscratchcswl = 0x349, // MRW Conditional scratch swap on level change (CLIC)
|
||||
mintthresh = 0x350, // MRW Interrupt-level threshold (CLIC) - addr subject to change
|
||||
mclicbase = 0x351, // MRW Base address for CLIC memory mapped registers (CLIC) - addr subject to change
|
||||
// Physical Memory Protection
|
||||
pmpcfg0 = 0x3A0,
|
||||
pmpcfg1 = 0x3A1,
|
||||
|
@ -170,7 +175,6 @@ enum riscv_csr {
|
|||
dscratch1 = 0x7B3
|
||||
};
|
||||
|
||||
|
||||
enum {
|
||||
PGSHIFT = 12,
|
||||
PTE_PPN_SHIFT = 10,
|
||||
|
@ -216,10 +220,13 @@ struct vm_info {
|
|||
|
||||
struct feature_config {
|
||||
uint64_t clic_base{0xc0000000};
|
||||
unsigned clic_int_ctl_bits{4};
|
||||
unsigned clic_num_irq{16};
|
||||
unsigned clic_num_trigger{0};
|
||||
uint64_t tcm_base{0x10000000};
|
||||
uint64_t tcm_size{0x8000};
|
||||
uint64_t io_address{0xf0000000};
|
||||
uint64_t io_addr_mask{0xf0000000};
|
||||
};
|
||||
|
||||
class trap_load_access_fault : public trap_access {
|
||||
|
@ -290,7 +297,7 @@ inline void write_reg_uint32(uint64_t offs, uint32_t& reg, const uint8_t *const
|
|||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
} // namespace arch
|
||||
} // namespace iss
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -1,5 +1,5 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (C) 2017, 2018, 2021 MINRES Technologies GmbH
|
||||
* Copyright (C) 2017 - 2023 MINRES Technologies GmbH
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -35,22 +35,22 @@
|
|||
#ifndef _RISCV_HART_MSU_VP_H
|
||||
#define _RISCV_HART_MSU_VP_H
|
||||
|
||||
#include "riscv_hart_common.h"
|
||||
#include "iss/arch/traits.h"
|
||||
#include "iss/instrumentation_if.h"
|
||||
#include "iss/log_categories.h"
|
||||
#include "iss/vm_if.h"
|
||||
#include "riscv_hart_common.h"
|
||||
#ifndef FMT_HEADER_ONLY
|
||||
#define FMT_HEADER_ONLY
|
||||
#endif
|
||||
#include <array>
|
||||
#include <elfio/elfio.hpp>
|
||||
#include <fmt/format.h>
|
||||
#include <functional>
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
#include <type_traits>
|
||||
#include <unordered_map>
|
||||
#include <functional>
|
||||
#include <util/bit_field.h>
|
||||
#include <util/ities.h>
|
||||
#include <util/sparse_array.h>
|
||||
|
@ -86,10 +86,11 @@ protected:
|
|||
"Load page fault", // d
|
||||
"Reserved", // e
|
||||
"Store/AMO page fault"}};
|
||||
const std::array<const char *, 12> irq_str = {
|
||||
{"User software interrupt", "Supervisor software interrupt", "Reserved", "Machine software interrupt",
|
||||
"User timer interrupt", "Supervisor timer interrupt", "Reserved", "Machine timer interrupt",
|
||||
"User external interrupt", "Supervisor external interrupt", "Reserved", "Machine external interrupt"}};
|
||||
const std::array<const char*, 12> irq_str = {{"User software interrupt", "Supervisor software interrupt", "Reserved",
|
||||
"Machine software interrupt", "User timer interrupt", "Supervisor timer interrupt",
|
||||
"Reserved", "Machine timer interrupt", "User external interrupt",
|
||||
"Supervisor external interrupt", "Reserved", "Machine external interrupt"}};
|
||||
|
||||
public:
|
||||
using core = BASE;
|
||||
using this_class = riscv_hart_msu_vp<BASE>;
|
||||
|
@ -107,7 +108,8 @@ public:
|
|||
template <typename T> class hart_state<T, typename std::enable_if<std::is_same<T, uint32_t>::value>::type> {
|
||||
public:
|
||||
BEGIN_BF_DECL(mstatus_t, T);
|
||||
// SD bit is read-only and is set when either the FS or XS bits encode a Dirty state (i.e., SD=((FS==11) OR XS==11)))
|
||||
// SD bit is read-only and is set when either the FS or XS bits encode a Dirty state (i.e., SD=((FS==11) OR
|
||||
// XS==11)))
|
||||
BF_FIELD(SD, 31, 1);
|
||||
// Trap SRET
|
||||
BF_FIELD(TSR, 22, 1);
|
||||
|
@ -121,7 +123,8 @@ public:
|
|||
BF_FIELD(SUM, 18, 1);
|
||||
// Modify PRiVilege
|
||||
BF_FIELD(MPRV, 17, 1);
|
||||
// status of additional user-mode extensions and associated state, All off/None dirty or clean, some on/None dirty, some clean/Some dirty
|
||||
// status of additional user-mode extensions and associated state, All off/None dirty or clean, some on/None
|
||||
// dirty, some clean/Some dirty
|
||||
BF_FIELD(XS, 15, 2);
|
||||
// floating-point unit status Off/Initial/Clean/Dirty
|
||||
BF_FIELD(FS, 13, 2);
|
||||
|
@ -162,20 +165,27 @@ public:
|
|||
return priv_lvl == PRIV_U ? 0x80000011UL : priv_lvl == PRIV_S ? 0x800de133UL : 0x807ff9ddUL;
|
||||
#else
|
||||
switch(priv_lvl) {
|
||||
case PRIV_U: return 0x80000011UL; // 0b1000 0000 0000 0000 0000 0000 0001 0001
|
||||
case PRIV_S: return 0x800de133UL; // 0b1000 0000 0000 1101 1110 0001 0011 0011
|
||||
default: return 0x807ff9ddUL; // 0b1000 0000 0111 1111 1111 1001 1011 1011
|
||||
case PRIV_U:
|
||||
return 0x80000011UL; // 0b1000 0000 0000 0000 0000 0000 0001 0001
|
||||
case PRIV_S:
|
||||
return 0x800de133UL; // 0b1000 0000 0000 1101 1110 0001 0011 0011
|
||||
default:
|
||||
return 0x807ff9ddUL; // 0b1000 0000 0111 1111 1111 1001 1011 1011
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline vm_info decode_vm_info(uint32_t state, T sptbr) {
|
||||
if (state == PRIV_M) return {0, 0, 0, 0};
|
||||
if(state == PRIV_M)
|
||||
return {0, 0, 0, 0};
|
||||
if(state <= PRIV_S)
|
||||
switch(bit_sub<31, 1>(sptbr)) {
|
||||
case 0: return {0, 0, 0, 0}; // off
|
||||
case 1: return {2, 10, 4, bit_sub<0, 22>(sptbr) << PGSHIFT}; // SV32
|
||||
default: abort();
|
||||
case 0:
|
||||
return {0, 0, 0, 0}; // off
|
||||
case 1:
|
||||
return {2, 10, 4, bit_sub<0, 22>(sptbr) << PGSHIFT}; // SV32
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
abort();
|
||||
return {0, 0, 0, 0}; // dummy
|
||||
|
@ -185,7 +195,8 @@ public:
|
|||
template <typename T> class hart_state<T, typename std::enable_if<std::is_same<T, uint64_t>::value>::type> {
|
||||
public:
|
||||
BEGIN_BF_DECL(mstatus_t, T);
|
||||
// SD bit is read-only and is set when either the FS or XS bits encode a Dirty state (i.e., SD=((FS==11) OR XS==11)))
|
||||
// SD bit is read-only and is set when either the FS or XS bits encode a Dirty state (i.e., SD=((FS==11) OR
|
||||
// XS==11)))
|
||||
BF_FIELD(SD, 63, 1);
|
||||
// value of XLEN for S-mode
|
||||
BF_FIELD(SXL, 34, 2);
|
||||
|
@ -203,7 +214,8 @@ public:
|
|||
BF_FIELD(SUM, 18, 1);
|
||||
// Modify PRiVilege
|
||||
BF_FIELD(MPRV, 17, 1);
|
||||
// status of additional user-mode extensions and associated state, All off/None dirty or clean, some on/None dirty, some clean/Some dirty
|
||||
// status of additional user-mode extensions and associated state, All off/None dirty or clean, some on/None
|
||||
// dirty, some clean/Some dirty
|
||||
BF_FIELD(XS, 15, 2);
|
||||
// floating-point unit status Off/Initial/Clean/Dirty
|
||||
BF_FIELD(FS, 13, 2);
|
||||
|
@ -249,23 +261,36 @@ public:
|
|||
static constexpr T get_mask(unsigned priv_lvl) {
|
||||
uint64_t ret;
|
||||
switch(priv_lvl) {
|
||||
case PRIV_U: ret = 0x8000000f00000011ULL;break; // 0b1...0 1111 0000 0000 0111 1111 1111 1001 1011 1011
|
||||
case PRIV_S: ret = 0x8000000f000de133ULL;break; // 0b1...0 0011 0000 0000 0000 1101 1110 0001 0011 0011
|
||||
default: ret = 0x8000000f007ff9ddULL;break; // 0b1...0 1111 0000 0000 0111 1111 1111 1001 1011 1011
|
||||
case PRIV_U:
|
||||
ret = 0x8000000f00000011ULL;
|
||||
break; // 0b1...0 1111 0000 0000 0111 1111 1111 1001 1011 1011
|
||||
case PRIV_S:
|
||||
ret = 0x8000000f000de133ULL;
|
||||
break; // 0b1...0 0011 0000 0000 0000 1101 1110 0001 0011 0011
|
||||
default:
|
||||
ret = 0x8000000f007ff9ddULL;
|
||||
break; // 0b1...0 1111 0000 0000 0111 1111 1111 1001 1011 1011
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline vm_info decode_vm_info(uint32_t state, T sptbr) {
|
||||
if (state == PRIV_M) return {0, 0, 0, 0};
|
||||
if(state == PRIV_M)
|
||||
return {0, 0, 0, 0};
|
||||
if(state <= PRIV_S)
|
||||
switch(bit_sub<60, 4>(sptbr)) {
|
||||
case 0: return {0, 0, 0, 0}; // off
|
||||
case 8: return {3, 9, 8, bit_sub<0, 44>(sptbr) << PGSHIFT};// SV39
|
||||
case 9: return {4, 9, 8, bit_sub<0, 44>(sptbr) << PGSHIFT};// SV48
|
||||
case 10: return {5, 9, 8, bit_sub<0, 44>(sptbr) << PGSHIFT};// SV57
|
||||
case 11: return {6, 9, 8, bit_sub<0, 44>(sptbr) << PGSHIFT};// SV64
|
||||
default: abort();
|
||||
case 0:
|
||||
return {0, 0, 0, 0}; // off
|
||||
case 8:
|
||||
return {3, 9, 8, bit_sub<0, 44>(sptbr) << PGSHIFT}; // SV39
|
||||
case 9:
|
||||
return {4, 9, 8, bit_sub<0, 44>(sptbr) << PGSHIFT}; // SV48
|
||||
case 10:
|
||||
return {5, 9, 8, bit_sub<0, 44>(sptbr) << PGSHIFT}; // SV57
|
||||
case 11:
|
||||
return {6, 9, 8, bit_sub<0, 44>(sptbr) << PGSHIFT}; // SV64
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
abort();
|
||||
return {0, 0, 0, 0}; // dummy
|
||||
|
@ -286,7 +311,7 @@ public:
|
|||
return m[mode];
|
||||
}
|
||||
|
||||
riscv_hart_msu_vp();
|
||||
riscv_hart_msu_vp(feature_config cfg = feature_config{});
|
||||
virtual ~riscv_hart_msu_vp() = default;
|
||||
|
||||
void reset(uint64_t address) override;
|
||||
|
@ -295,10 +320,10 @@ public:
|
|||
|
||||
phys_addr_t virt2phys(const iss::addr_t& addr) override;
|
||||
|
||||
iss::status read(const address_type type, const access_type access, const uint32_t space,
|
||||
const uint64_t addr, const unsigned length, uint8_t *const data) override;
|
||||
iss::status write(const address_type type, const access_type access, const uint32_t space,
|
||||
const uint64_t addr, const unsigned length, const uint8_t *const data) override;
|
||||
iss::status read(const address_type type, const access_type access, const uint32_t space, const uint64_t addr, const unsigned length,
|
||||
uint8_t* const data) override;
|
||||
iss::status write(const address_type type, const access_type access, const uint32_t space, const uint64_t addr, const unsigned length,
|
||||
const uint8_t* const data) override;
|
||||
|
||||
uint64_t enter_trap(uint64_t flags) override { return riscv_hart_msu_vp::enter_trap(flags, fault_data, fault_data); }
|
||||
uint64_t enter_trap(uint64_t flags, uint64_t addr, uint64_t instr) override;
|
||||
|
@ -306,23 +331,15 @@ public:
|
|||
void wait_until(uint64_t flags) override;
|
||||
|
||||
void disass_output(uint64_t pc, const std::string instr) override {
|
||||
CLOG(INFO, disass) << fmt::format("0x{:016x} {:40} [p:{};s:0x{:x};c:{}]",
|
||||
pc, instr, lvl[this->reg.PRIV], (reg_t)state.mstatus, this->reg.ccount + cycle_offset);
|
||||
CLOG(INFO, disass) << fmt::format("0x{:016x} {:40} [p:{};s:0x{:x};c:{}]", pc, instr, lvl[this->reg.PRIV], (reg_t)state.mstatus,
|
||||
this->reg.icount + cycle_offset);
|
||||
};
|
||||
|
||||
iss::instrumentation_if* get_instrumentation_if() override { return &instr_if; }
|
||||
|
||||
void setMemReadCb(std::function<iss::status(phys_addr_t, unsigned, uint8_t* const)> const& memReadCb) {
|
||||
mem_read_cb = memReadCb;
|
||||
}
|
||||
void set_csr(unsigned addr, reg_t val) { csr[addr & csr.page_addr_mask] = val; }
|
||||
|
||||
void setMemWriteCb(std::function<iss::status(phys_addr_t, unsigned, const uint8_t* const)> const& memWriteCb) {
|
||||
mem_write_cb = memWriteCb;
|
||||
}
|
||||
|
||||
void set_csr(unsigned addr, reg_t val){
|
||||
csr[addr & csr.page_addr_mask] = val;
|
||||
}
|
||||
void set_irq_num(unsigned i) { mcause_max_irq = 1 << util::ilog2(i); }
|
||||
|
||||
protected:
|
||||
struct riscv_instrumentation_if : public iss::instrumentation_if {
|
||||
|
@ -336,15 +353,25 @@ protected:
|
|||
*/
|
||||
const std::string core_type_name() const override { return traits<BASE>::core_type; }
|
||||
|
||||
virtual uint64_t get_pc() { return arch.get_pc(); };
|
||||
uint64_t get_pc() override { return arch.reg.PC; }
|
||||
|
||||
virtual uint64_t get_next_pc() { return arch.get_next_pc(); };
|
||||
uint64_t get_next_pc() override { return arch.reg.NEXT_PC; }
|
||||
|
||||
uint64_t get_instr_count() { return arch.reg.icount; }
|
||||
uint64_t get_instr_word() override { return arch.reg.instruction; }
|
||||
|
||||
uint64_t get_instr_count() override { return arch.reg.icount; }
|
||||
|
||||
uint64_t get_pendig_traps() override { return arch.reg.trap_state; }
|
||||
|
||||
uint64_t get_total_cycles() override { return arch.reg.icount + arch.cycle_offset; }
|
||||
|
||||
virtual void set_curr_instr_cycles(unsigned cycles) { arch.cycle_offset += cycles - 1; };
|
||||
void update_last_instr_cycles(unsigned cycles) override { arch.cycle_offset += cycles - 1; }
|
||||
|
||||
bool is_branch_taken() override { return arch.reg.last_branch; }
|
||||
|
||||
unsigned get_reg_num() override { return traits<BASE>::NUM_REGS; }
|
||||
|
||||
unsigned get_reg_size(unsigned num) override { return traits<BASE>::reg_bit_widths[num]; }
|
||||
|
||||
riscv_hart_msu_vp<BASE>& arch;
|
||||
};
|
||||
|
@ -383,16 +410,17 @@ protected:
|
|||
std::unordered_map<unsigned, rd_csr_f> csr_rd_cb;
|
||||
std::unordered_map<unsigned, wr_csr_f> csr_wr_cb;
|
||||
|
||||
private:
|
||||
iss::status read_reg(unsigned addr, reg_t &val);
|
||||
iss::status write_reg(unsigned addr, reg_t val);
|
||||
std::vector<uint8_t> tcm;
|
||||
|
||||
iss::status read_csr_reg(unsigned addr, reg_t& val);
|
||||
iss::status write_csr_reg(unsigned addr, reg_t val);
|
||||
iss::status read_null(unsigned addr, reg_t& val);
|
||||
iss::status write_null(unsigned addr, reg_t val) { return iss::status::Ok; }
|
||||
iss::status read_cycle(unsigned addr, reg_t& val);
|
||||
iss::status write_cycle(unsigned addr, reg_t val);
|
||||
iss::status read_instret(unsigned addr, reg_t& val);
|
||||
iss::status write_instret(unsigned addr, reg_t val);
|
||||
iss::status read_mtvec(unsigned addr, reg_t &val);
|
||||
iss::status read_tvec(unsigned addr, reg_t& val);
|
||||
iss::status read_time(unsigned addr, reg_t& val);
|
||||
iss::status read_status(unsigned addr, reg_t& val);
|
||||
iss::status write_status(unsigned addr, reg_t val);
|
||||
|
@ -400,6 +428,8 @@ private:
|
|||
iss::status read_ie(unsigned addr, reg_t& val);
|
||||
iss::status write_ie(unsigned addr, reg_t val);
|
||||
iss::status read_ip(unsigned addr, reg_t& val);
|
||||
iss::status write_ideleg(unsigned addr, reg_t val);
|
||||
iss::status write_edeleg(unsigned addr, reg_t val);
|
||||
iss::status read_hartid(unsigned addr, reg_t& val);
|
||||
iss::status write_epc(unsigned addr, reg_t val);
|
||||
iss::status read_satp(unsigned addr, reg_t& val);
|
||||
|
@ -410,18 +440,11 @@ private:
|
|||
virtual iss::status read_custom_csr_reg(unsigned addr, reg_t& val) { return iss::status::Err; };
|
||||
virtual iss::status write_custom_csr_reg(unsigned addr, reg_t val) { return iss::status::Err; };
|
||||
|
||||
void register_custom_csr_rd(unsigned addr){
|
||||
csr_rd_cb[addr] = &this_class::read_custom_csr_reg;
|
||||
}
|
||||
void register_custom_csr_wr(unsigned addr){
|
||||
csr_wr_cb[addr] = &this_class::write_custom_csr_reg;
|
||||
}
|
||||
void register_custom_csr_rd(unsigned addr) { csr_rd_cb[addr] = &this_class::read_custom_csr_reg; }
|
||||
void register_custom_csr_wr(unsigned addr) { csr_wr_cb[addr] = &this_class::write_custom_csr_reg; }
|
||||
|
||||
reg_t mhartid_reg{0x0};
|
||||
std::function<iss::status(phys_addr_t, unsigned, uint8_t *const)>mem_read_cb;
|
||||
std::function<iss::status(phys_addr_t, unsigned, const uint8_t *const)> mem_write_cb;
|
||||
|
||||
protected:
|
||||
void check_interrupt();
|
||||
};
|
||||
|
||||
|
@ -429,6 +452,7 @@ template <typename BASE>
|
|||
riscv_hart_msu_vp<BASE>::riscv_hart_msu_vp()
|
||||
: state()
|
||||
, instr_if(*this) {
|
||||
this->_has_mmu = true;
|
||||
// reset values
|
||||
csr[misa] = traits<BASE>::MISA_VAL;
|
||||
csr[mvendorid] = 0x669;
|
||||
|
@ -438,49 +462,53 @@ riscv_hart_msu_vp<BASE>::riscv_hart_msu_vp()
|
|||
uart_buf.str("");
|
||||
for(unsigned addr = mhpmcounter3; addr <= mhpmcounter31; ++addr) {
|
||||
csr_rd_cb[addr] = &this_class::read_null;
|
||||
csr_wr_cb[addr] = &this_class::write_reg;
|
||||
csr_wr_cb[addr] = &this_class::write_csr_reg;
|
||||
}
|
||||
for(unsigned addr = mhpmcounter3h; addr <= mhpmcounter31h; ++addr) {
|
||||
csr_rd_cb[addr] = &this_class::read_null;
|
||||
csr_wr_cb[addr] = &this_class::write_reg;
|
||||
csr_wr_cb[addr] = &this_class::write_csr_reg;
|
||||
}
|
||||
for(unsigned addr = mhpmevent3; addr <= mhpmevent31; ++addr) {
|
||||
csr_rd_cb[addr] = &this_class::read_null;
|
||||
csr_wr_cb[addr] = &this_class::write_reg;
|
||||
csr_wr_cb[addr] = &this_class::write_csr_reg;
|
||||
}
|
||||
for(unsigned addr = hpmcounter3; addr <= hpmcounter31; ++addr) {
|
||||
csr_rd_cb[addr] = &this_class::read_null;
|
||||
}
|
||||
for(unsigned addr = cycleh; addr <= hpmcounter31h; ++addr) {
|
||||
csr_rd_cb[addr] = &this_class::read_null;
|
||||
//csr_wr_cb[addr] = &this_class::write_reg;
|
||||
// csr_wr_cb[addr] = &this_class::write_csr_reg;
|
||||
}
|
||||
// common regs
|
||||
const std::array<unsigned, 22> addrs{{
|
||||
misa, mvendorid, marchid, mimpid,
|
||||
mepc, mtvec, mscratch, mcause, mtval, mscratch,
|
||||
sepc, stvec, sscratch, scause, stval, sscratch,
|
||||
uepc, utvec, uscratch, ucause, utval, uscratch
|
||||
}};
|
||||
const std::array<unsigned, 22> addrs{{misa, mvendorid, marchid, mimpid, mepc, mtvec, mscratch, mcause,
|
||||
mtval, mscratch, sepc, stvec, sscratch, scause, stval, sscratch,
|
||||
uepc, utvec, uscratch, ucause, utval, uscratch}};
|
||||
for(auto addr : addrs) {
|
||||
csr_rd_cb[addr] = &this_class::read_reg;
|
||||
csr_wr_cb[addr] = &this_class::write_reg;
|
||||
csr_rd_cb[addr] = &this_class::read_csr_reg;
|
||||
csr_wr_cb[addr] = &this_class::write_csr_reg;
|
||||
}
|
||||
// special handling & overrides
|
||||
csr_rd_cb[time] = &this_class::read_time;
|
||||
if(traits<BASE>::XLEN == 32)
|
||||
csr_rd_cb[timeh] = &this_class::read_time;
|
||||
csr_rd_cb[cycle] = &this_class::read_cycle;
|
||||
if(traits<BASE>::XLEN == 32)
|
||||
csr_rd_cb[cycleh] = &this_class::read_cycle;
|
||||
csr_rd_cb[instret] = &this_class::read_instret;
|
||||
if(traits<BASE>::XLEN == 32)
|
||||
csr_rd_cb[instreth] = &this_class::read_instret;
|
||||
|
||||
csr_rd_cb[mcycle] = &this_class::read_cycle;
|
||||
csr_wr_cb[mcycle] = &this_class::write_cycle;
|
||||
if(traits<BASE>::XLEN == 32)
|
||||
csr_rd_cb[mcycleh] = &this_class::read_cycle;
|
||||
if(traits<BASE>::XLEN == 32)
|
||||
csr_wr_cb[mcycleh] = &this_class::write_cycle;
|
||||
csr_rd_cb[minstret] = &this_class::read_instret;
|
||||
csr_wr_cb[minstret] = &this_class::write_instret;
|
||||
if(traits<BASE>::XLEN == 32)
|
||||
csr_rd_cb[minstreth] = &this_class::read_instret;
|
||||
if(traits<BASE>::XLEN == 32)
|
||||
csr_wr_cb[minstreth] = &this_class::write_instret;
|
||||
csr_rd_cb[mstatus] = &this_class::read_status;
|
||||
csr_wr_cb[mstatus] = &this_class::write_status;
|
||||
|
@ -531,36 +559,38 @@ template <typename BASE> std::pair<uint64_t, bool> riscv_hart_msu_vp<BASE>::load
|
|||
if(fp) {
|
||||
std::array<char, 5> buf;
|
||||
auto n = fread(buf.data(), 1, 4, fp);
|
||||
if (n != 4) throw std::runtime_error("input file has insufficient size");
|
||||
fclose(fp);
|
||||
if(n != 4)
|
||||
throw std::runtime_error("input file has insufficient size");
|
||||
buf[4] = 0;
|
||||
if(strcmp(buf.data() + 1, "ELF") == 0) {
|
||||
fclose(fp);
|
||||
// Create elfio reader
|
||||
ELFIO::elfio reader;
|
||||
// Load ELF data
|
||||
if (!reader.load(name)) throw std::runtime_error("could not process elf file");
|
||||
if(!reader.load(name))
|
||||
throw std::runtime_error("could not process elf file");
|
||||
// check elf properties
|
||||
if(reader.get_class() != ELFCLASS32)
|
||||
if (sizeof(reg_t) == 4) throw std::runtime_error("wrong elf class in file");
|
||||
if (reader.get_type() != ET_EXEC) throw std::runtime_error("wrong elf type in file");
|
||||
if (reader.get_machine() != EM_RISCV) throw std::runtime_error("wrong elf machine in file");
|
||||
if(sizeof(reg_t) == 4)
|
||||
throw std::runtime_error("wrong elf class in file");
|
||||
if(reader.get_type() != ET_EXEC)
|
||||
throw std::runtime_error("wrong elf type in file");
|
||||
if(reader.get_machine() != EM_RISCV)
|
||||
throw std::runtime_error("wrong elf machine in file");
|
||||
auto entry = reader.get_entry();
|
||||
for(const auto pseg : reader.segments) {
|
||||
const auto fsize = pseg->get_file_size(); // 0x42c/0x0
|
||||
const auto seg_data = pseg->get_data();
|
||||
if(fsize > 0) {
|
||||
auto res = this->write(iss::address_type::PHYSICAL, iss::access_type::DEBUG_WRITE,
|
||||
traits<BASE>::MEM, pseg->get_physical_address(),
|
||||
fsize, reinterpret_cast<const uint8_t *const>(seg_data));
|
||||
auto res = this->write(iss::address_type::PHYSICAL, iss::access_type::DEBUG_WRITE, traits<BASE>::MEM,
|
||||
pseg->get_physical_address(), fsize, reinterpret_cast<const uint8_t* const>(seg_data));
|
||||
if(res != iss::Ok)
|
||||
LOG(ERROR) << "problem writing " << fsize << "bytes to 0x" << std::hex
|
||||
<< pseg->get_physical_address();
|
||||
LOG(ERR) << "problem writing " << fsize << "bytes to 0x" << std::hex << pseg->get_physical_address();
|
||||
}
|
||||
}
|
||||
for(const auto sec : reader.sections) {
|
||||
if(sec->get_name() == ".symtab") {
|
||||
if ( SHT_SYMTAB == sec->get_type() ||
|
||||
SHT_DYNSYM == sec->get_type() ) {
|
||||
if(SHT_SYMTAB == sec->get_type() || SHT_DYNSYM == sec->get_type()) {
|
||||
ELFIO::symbol_section_accessor symbols(reader, sec);
|
||||
auto sym_no = symbols.get_symbols_num();
|
||||
std::string name;
|
||||
|
@ -583,18 +613,17 @@ template <typename BASE> std::pair<uint64_t, bool> riscv_hart_msu_vp<BASE>::load
|
|||
tohost = sec->get_address();
|
||||
fromhost = tohost + 0x40;
|
||||
}
|
||||
|
||||
}
|
||||
return std::make_pair(entry, true);
|
||||
}
|
||||
throw std::runtime_error("memory load file is not a valid elf file");
|
||||
throw std::runtime_error(fmt::format("memory load file {} is not a valid elf file", name));
|
||||
}
|
||||
throw std::runtime_error("memory load file not found");
|
||||
throw std::runtime_error(fmt::format("memory load file not found, check if {} is a valid file", name));
|
||||
}
|
||||
|
||||
template <typename BASE>
|
||||
iss::status riscv_hart_msu_vp<BASE>::read(const address_type type, const access_type access, const uint32_t space,
|
||||
const uint64_t addr, const unsigned length, uint8_t *const data) {
|
||||
iss::status riscv_hart_msu_vp<BASE>::read(const address_type type, const access_type access, const uint32_t space, const uint64_t addr,
|
||||
const unsigned length, uint8_t* const data) {
|
||||
#ifndef NDEBUG
|
||||
if(access && iss::access_type::DEBUG) {
|
||||
LOG(TRACEALL) << "debug read of " << length << " bytes @addr 0x" << std::hex << addr;
|
||||
|
@ -607,13 +636,20 @@ iss::status riscv_hart_msu_vp<BASE>::read(const address_type type, const access_
|
|||
try {
|
||||
switch(space) {
|
||||
case traits<BASE>::MEM: {
|
||||
if (unlikely((access == iss::access_type::FETCH || access == iss::access_type::DEBUG_FETCH) && (addr & 0x1) == 1)) {
|
||||
auto alignment = is_fetch(access) ? (traits<BASE>::MISA_VAL & 0x100 ? 2 : 4) : length;
|
||||
if(unlikely(is_fetch(access) && (addr & (alignment - 1)))) {
|
||||
fault_data = addr;
|
||||
if (access && iss::access_type::DEBUG) throw trap_access(0, addr);
|
||||
if(access && iss::access_type::DEBUG)
|
||||
throw trap_access(0, addr);
|
||||
this->reg.trap_state = (1 << 31); // issue trap 0
|
||||
return iss::Err;
|
||||
}
|
||||
try {
|
||||
if(!is_debug(access) && (addr & (alignment - 1))) {
|
||||
this->reg.trap_state = 1 << 31 | 4 << 16;
|
||||
fault_data = addr;
|
||||
return iss::Err;
|
||||
}
|
||||
if(unlikely((addr & ~PGMASK) != ((addr + length - 1) & ~PGMASK))) { // we may cross a page boundary
|
||||
vm_info vm = hart_state_type::decode_vm_info(this->reg.PRIV, state.satp);
|
||||
if(vm.levels != 0) { // VM is active
|
||||
|
@ -625,10 +661,8 @@ iss::status riscv_hart_msu_vp<BASE>::read(const address_type type, const access_
|
|||
return res;
|
||||
}
|
||||
}
|
||||
auto res = type==iss::address_type::PHYSICAL?
|
||||
read_mem( BASE::v2p(phys_addr_t{access, space, addr}), length, data):
|
||||
read_mem( BASE::v2p(iss::addr_t{access, type, space, addr}), length, data);
|
||||
if (unlikely(res != iss::Ok)){
|
||||
auto res = read_mem(BASE::v2p(iss::addr_t{access, type, space, addr}), length, data);
|
||||
if(unlikely(res != iss::Ok && (access & access_type::DEBUG) == 0)) {
|
||||
this->reg.trap_state = (1 << 31) | (5 << 16); // issue trap 5 (load access fault
|
||||
fault_data = addr;
|
||||
}
|
||||
|
@ -640,11 +674,13 @@ iss::status riscv_hart_msu_vp<BASE>::read(const address_type type, const access_
|
|||
}
|
||||
} break;
|
||||
case traits<BASE>::CSR: {
|
||||
if (length != sizeof(reg_t)) return iss::Err;
|
||||
if(length != sizeof(reg_t))
|
||||
return iss::Err;
|
||||
return read_csr(addr, *reinterpret_cast<reg_t* const>(data));
|
||||
} break;
|
||||
case traits<BASE>::FENCE: {
|
||||
if ((addr + length) > mem.size()) return iss::Err;
|
||||
if((addr + length) > mem.size())
|
||||
return iss::Err;
|
||||
switch(addr) {
|
||||
case 2: // SFENCE:VMA lower
|
||||
case 3: { // SFENCE:VMA upper
|
||||
|
@ -671,33 +707,33 @@ iss::status riscv_hart_msu_vp<BASE>::read(const address_type type, const access_
|
|||
}
|
||||
return iss::Ok;
|
||||
} catch(trap_access& ta) {
|
||||
this->reg.trap_state = (1 << 31) | ta.id;
|
||||
this->reg.trap_state = (1UL << 31) | ta.id;
|
||||
fault_data = ta.addr;
|
||||
return iss::Err;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename BASE>
|
||||
iss::status riscv_hart_msu_vp<BASE>::write(const address_type type, const access_type access, const uint32_t space,
|
||||
const uint64_t addr, const unsigned length, const uint8_t *const data) {
|
||||
iss::status riscv_hart_msu_vp<BASE>::write(const address_type type, const access_type access, const uint32_t space, const uint64_t addr,
|
||||
const unsigned length, const uint8_t* const data) {
|
||||
#ifndef NDEBUG
|
||||
const char* prefix = (access && iss::access_type::DEBUG) ? "debug " : "";
|
||||
switch(length) {
|
||||
case 8:
|
||||
LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint64_t *)&data[0] << std::dec
|
||||
<< ") @addr 0x" << std::hex << addr;
|
||||
LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint64_t*)&data[0] << std::dec << ") @addr 0x"
|
||||
<< std::hex << addr;
|
||||
break;
|
||||
case 4:
|
||||
LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint32_t *)&data[0] << std::dec
|
||||
<< ") @addr 0x" << std::hex << addr;
|
||||
LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint32_t*)&data[0] << std::dec << ") @addr 0x"
|
||||
<< std::hex << addr;
|
||||
break;
|
||||
case 2:
|
||||
LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint16_t *)&data[0] << std::dec
|
||||
<< ") @addr 0x" << std::hex << addr;
|
||||
LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint16_t*)&data[0] << std::dec << ") @addr 0x"
|
||||
<< std::hex << addr;
|
||||
break;
|
||||
case 1:
|
||||
LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << (uint16_t)data[0] << std::dec
|
||||
<< ") @addr 0x" << std::hex << addr;
|
||||
LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << (uint16_t)data[0] << std::dec << ") @addr 0x"
|
||||
<< std::hex << addr;
|
||||
break;
|
||||
default:
|
||||
LOG(TRACE) << prefix << "write of " << length << " bytes @addr " << addr;
|
||||
|
@ -708,10 +744,12 @@ iss::status riscv_hart_msu_vp<BASE>::write(const address_type type, const access
|
|||
case traits<BASE>::MEM: {
|
||||
if(unlikely((access && iss::access_type::FETCH) && (addr & 0x1) == 1)) {
|
||||
fault_data = addr;
|
||||
if (access && iss::access_type::DEBUG) throw trap_access(0, addr);
|
||||
if(access && iss::access_type::DEBUG)
|
||||
throw trap_access(0, addr);
|
||||
this->reg.trap_state = (1 << 31); // issue trap 0
|
||||
return iss::Err;
|
||||
}
|
||||
phys_addr_t paddr = BASE::v2p(iss::addr_t{access, type, space, addr});
|
||||
try {
|
||||
if(unlikely((addr & ~PGMASK) != ((addr + length - 1) & ~PGMASK))) { // we may cross a page boundary
|
||||
vm_info vm = hart_state_type::decode_vm_info(this->reg.PRIV, state.satp);
|
||||
|
@ -724,22 +762,20 @@ iss::status riscv_hart_msu_vp<BASE>::write(const address_type type, const access
|
|||
return res;
|
||||
}
|
||||
}
|
||||
auto res = type==iss::address_type::PHYSICAL?
|
||||
write_mem(phys_addr_t{access, space, addr}, length, data):
|
||||
write_mem(BASE::v2p(iss::addr_t{access, type, space, addr}), length, data);
|
||||
if (unlikely(res != iss::Ok)) {
|
||||
this->reg.trap_state = (1 << 31) | (7 << 16); // issue trap 7 (Store/AMO access fault)
|
||||
auto res = write_mem(paddr, length, data);
|
||||
if(unlikely(res != iss::Ok && (access & access_type::DEBUG) == 0)) {
|
||||
this->reg.trap_state = (1UL << 31) | (7UL << 16); // issue trap 7 (Store/AMO access fault)
|
||||
fault_data = addr;
|
||||
}
|
||||
return res;
|
||||
} catch(trap_access& ta) {
|
||||
this->reg.trap_state = (1 << 31) | ta.id;
|
||||
this->reg.trap_state = (1UL << 31) | ta.id;
|
||||
fault_data = ta.addr;
|
||||
return iss::Err;
|
||||
}
|
||||
|
||||
phys_addr_t paddr = BASE::v2p(iss::addr_t{access, type, space, addr});
|
||||
if ((paddr.val + length) > mem.size()) return iss::Err;
|
||||
if((paddr.val + length) > mem.size())
|
||||
return iss::Err;
|
||||
switch(paddr.val) {
|
||||
case 0x10013000: // UART0 base, TXFIFO reg
|
||||
case 0x10023000: // UART1 base, TXFIFO reg
|
||||
|
@ -756,7 +792,8 @@ iss::status riscv_hart_msu_vp<BASE>::write(const address_type type, const access
|
|||
auto offs = paddr.val & mem.page_addr_mask;
|
||||
std::copy(data, data + length, p.data() + offs);
|
||||
auto& x = *(p.data() + offs + 3);
|
||||
if (x & 0x40) x |= 0x80; // hfroscrdy = 1 if hfroscen==1
|
||||
if(x & 0x40)
|
||||
x |= 0x80; // hfroscrdy = 1 if hfroscen==1
|
||||
return iss::Ok;
|
||||
}
|
||||
case 0x10008008: { // HFROSC base, pllcfg reg
|
||||
|
@ -767,15 +804,18 @@ iss::status riscv_hart_msu_vp<BASE>::write(const address_type type, const access
|
|||
x |= 0x80; // set pll lock upon writing
|
||||
return iss::Ok;
|
||||
} break;
|
||||
default: {}
|
||||
default: {
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case traits<BASE>::CSR: {
|
||||
if (length != sizeof(reg_t)) return iss::Err;
|
||||
if(length != sizeof(reg_t))
|
||||
return iss::Err;
|
||||
return write_csr(addr, *reinterpret_cast<const reg_t*>(data));
|
||||
} break;
|
||||
case traits<BASE>::FENCE: {
|
||||
if ((addr + length) > mem.size()) return iss::Err;
|
||||
if((addr + length) > mem.size())
|
||||
return iss::Err;
|
||||
switch(addr) {
|
||||
case 2:
|
||||
case 3: {
|
||||
|
@ -798,14 +838,15 @@ iss::status riscv_hart_msu_vp<BASE>::write(const address_type type, const access
|
|||
}
|
||||
return iss::Ok;
|
||||
} catch(trap_access& ta) {
|
||||
this->reg.trap_state = (1 << 31) | ta.id;
|
||||
this->reg.trap_state = (1UL << 31) | ta.id;
|
||||
fault_data = ta.addr;
|
||||
return iss::Err;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::read_csr(unsigned addr, reg_t& val) {
|
||||
if (addr >= csr.size()) return iss::Err;
|
||||
if(addr >= csr.size())
|
||||
return iss::Err;
|
||||
auto req_priv_lvl = (addr >> 8) & 0x3;
|
||||
if(this->reg.PRIV < req_priv_lvl) // not having required privileges
|
||||
throw illegal_instruction_fault(this->fault_data);
|
||||
|
@ -816,7 +857,8 @@ template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::read_csr(unsigned
|
|||
}
|
||||
|
||||
template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::write_csr(unsigned addr, reg_t val) {
|
||||
if (addr >= csr.size()) return iss::Err;
|
||||
if(addr >= csr.size())
|
||||
return iss::Err;
|
||||
auto req_priv_lvl = (addr >> 8) & 0x3;
|
||||
if(this->reg.PRIV < req_priv_lvl) // not having required privileges
|
||||
throw illegal_instruction_fault(this->fault_data);
|
||||
|
@ -843,21 +885,20 @@ template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::write_reg(unsigned
|
|||
return iss::Ok;
|
||||
}
|
||||
|
||||
template <typename BASE> iss::status riscv_hart_m_p<BASE>::read_cycle(unsigned addr, reg_t &val) {
|
||||
template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::read_cycle(unsigned addr, reg_t& val) {
|
||||
auto cycle_val = this->reg.icount + cycle_offset;
|
||||
if(addr == mcycle) {
|
||||
val = static_cast<reg_t>(cycle_val);
|
||||
} else if(addr == mcycleh) {
|
||||
if (sizeof(typename traits<BASE>::reg_t) != 4) return iss::Err;
|
||||
if(sizeof(typename traits<BASE>::reg_t) != 4)
|
||||
return iss::Err;
|
||||
val = static_cast<reg_t>(cycle_val >> 32);
|
||||
}
|
||||
return iss::Ok;
|
||||
}
|
||||
|
||||
template <typename BASE> iss::status riscv_hart_m_p<BASE>::write_cycle(unsigned addr, reg_t val) {
|
||||
template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::write_cycle(unsigned addr, reg_t val) {
|
||||
if(sizeof(typename traits<BASE>::reg_t) != 4) {
|
||||
if (addr == mcycleh)
|
||||
return iss::Err;
|
||||
mcycle_csr = static_cast<uint64_t>(val);
|
||||
} else {
|
||||
if(addr == mcycle) {
|
||||
|
@ -870,20 +911,17 @@ template <typename BASE> iss::status riscv_hart_m_p<BASE>::write_cycle(unsigned
|
|||
return iss::Ok;
|
||||
}
|
||||
|
||||
template <typename BASE> iss::status riscv_hart_m_p<BASE>::read_instret(unsigned addr, reg_t &val) {
|
||||
template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::read_instret(unsigned addr, reg_t& val) {
|
||||
if((addr & 0xff) == (minstret & 0xff)) {
|
||||
val = static_cast<reg_t>(this->reg.instret);
|
||||
} else if((addr & 0xff) == (minstreth & 0xff)) {
|
||||
if (sizeof(typename traits<BASE>::reg_t) != 4) return iss::Err;
|
||||
val = static_cast<reg_t>(this->reg.instret >> 32);
|
||||
}
|
||||
return iss::Ok;
|
||||
}
|
||||
|
||||
template <typename BASE> iss::status riscv_hart_m_p<BASE>::write_instret(unsigned addr, reg_t val) {
|
||||
template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::write_instret(unsigned addr, reg_t val) {
|
||||
if(sizeof(typename traits<BASE>::reg_t) != 4) {
|
||||
if ((addr&0xff) == (minstreth&0xff))
|
||||
return iss::Err;
|
||||
this->reg.instret = static_cast<uint64_t>(val);
|
||||
} else {
|
||||
if((addr & 0xff) == (minstret & 0xff)) {
|
||||
|
@ -896,18 +934,19 @@ template <typename BASE> iss::status riscv_hart_m_p<BASE>::write_instret(unsigne
|
|||
return iss::Ok;
|
||||
}
|
||||
|
||||
template <typename BASE> iss::status riscv_hart_m_p<BASE>::read_time(unsigned addr, reg_t &val) {
|
||||
template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::read_time(unsigned addr, reg_t& val) {
|
||||
uint64_t time_val = this->reg.icount / (100000000 / 32768 - 1); //-> ~3052;
|
||||
if(addr == time) {
|
||||
val = static_cast<reg_t>(time_val);
|
||||
} else if(addr == timeh) {
|
||||
if (sizeof(typename traits<BASE>::reg_t) != 4) return iss::Err;
|
||||
if(sizeof(typename traits<BASE>::reg_t) != 4)
|
||||
return iss::Err;
|
||||
val = static_cast<reg_t>(time_val >> 32);
|
||||
}
|
||||
return iss::Ok;
|
||||
}
|
||||
|
||||
template <typename BASE> iss::status riscv_hart_m_p<BASE>::read_tvec(unsigned addr, reg_t &val) {
|
||||
template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::read_tvec(unsigned addr, reg_t& val) {
|
||||
val = csr[addr] & ~2;
|
||||
return iss::Ok;
|
||||
}
|
||||
|
@ -933,8 +972,10 @@ template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::write_cause(unsign
|
|||
|
||||
template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::read_ie(unsigned addr, reg_t& val) {
|
||||
val = csr[mie];
|
||||
if (addr < mie) val &= csr[mideleg];
|
||||
if (addr < sie) val &= csr[sideleg];
|
||||
if(addr < mie)
|
||||
val &= csr[mideleg];
|
||||
if(addr < sie)
|
||||
val &= csr[sideleg];
|
||||
return iss::Ok;
|
||||
}
|
||||
|
||||
|
@ -953,8 +994,10 @@ template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::write_ie(unsigned
|
|||
|
||||
template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::read_ip(unsigned addr, reg_t& val) {
|
||||
val = csr[mip];
|
||||
if (addr < mip) val &= csr[mideleg];
|
||||
if (addr < sip) val &= csr[sideleg];
|
||||
if(addr < mip)
|
||||
val &= csr[mideleg];
|
||||
if(addr < sip)
|
||||
val &= csr[sideleg];
|
||||
return iss::Ok;
|
||||
}
|
||||
|
||||
|
@ -1019,22 +1062,8 @@ template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::write_fcsr(unsigne
|
|||
return iss::Ok;
|
||||
}
|
||||
|
||||
template <typename BASE>
|
||||
iss::status riscv_hart_msu_vp<BASE>::read_mem(phys_addr_t paddr, unsigned length, uint8_t *const data) {
|
||||
if(mem_read_cb) return mem_read_cb(paddr, length, data);
|
||||
template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::read_mem(phys_addr_t paddr, unsigned length, uint8_t* const data) {
|
||||
switch(paddr.val) {
|
||||
case 0x0200BFF8: { // CLINT base, mtime reg
|
||||
if (sizeof(reg_t) < length) return iss::Err;
|
||||
reg_t time_val;
|
||||
this->read_csr(time, time_val);
|
||||
std::copy((uint8_t *)&time_val, ((uint8_t *)&time_val) + length, data);
|
||||
} break;
|
||||
case 0x10008000: {
|
||||
const mem_type::page_type &p = mem(paddr.val / mem.page_size);
|
||||
uint64_t offs = paddr.val & mem.page_addr_mask;
|
||||
std::copy(p.data() + offs, p.data() + offs + length, data);
|
||||
if (this->reg.icount > 30000) data[3] |= 0x80;
|
||||
} break;
|
||||
default: {
|
||||
for(auto offs = 0U; offs < length; ++offs) {
|
||||
*(data + offs) = mem[(paddr.val + offs) % mem.size()];
|
||||
|
@ -1044,43 +1073,23 @@ iss::status riscv_hart_msu_vp<BASE>::read_mem(phys_addr_t paddr, unsigned length
|
|||
return iss::Ok;
|
||||
}
|
||||
|
||||
template <typename BASE>
|
||||
iss::status riscv_hart_msu_vp<BASE>::write_mem(phys_addr_t paddr, unsigned length, const uint8_t *const data) {
|
||||
if(mem_write_cb) return mem_write_cb(paddr, length, data);
|
||||
template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::write_mem(phys_addr_t paddr, unsigned length, const uint8_t* const data) {
|
||||
switch(paddr.val) {
|
||||
case 0x10013000: // UART0 base, TXFIFO reg
|
||||
case 0x10023000: // UART1 base, TXFIFO reg
|
||||
uart_buf << (char)data[0];
|
||||
case 0xFFFF0000: // UART0 base, TXFIFO reg
|
||||
if(((char)data[0]) == '\n' || data[0] == 0) {
|
||||
// LOG(INFO)<<"UART"<<((paddr.val>>16)&0x3)<<" send
|
||||
// '"<<uart_buf.str()<<"'";
|
||||
std::cout << uart_buf.str();
|
||||
LOG(INFO) << "UART" << ((paddr.val >> 12) & 0x3) << " send '" << uart_buf.str() << "'";
|
||||
uart_buf.str("");
|
||||
}
|
||||
} else if(((char)data[0]) != '\r')
|
||||
uart_buf << (char)data[0];
|
||||
break;
|
||||
case 0x10008000: { // HFROSC base, hfrosccfg reg
|
||||
mem_type::page_type &p = mem(paddr.val / mem.page_size);
|
||||
size_t offs = paddr.val & mem.page_addr_mask;
|
||||
std::copy(data, data + length, p.data() + offs);
|
||||
uint8_t &x = *(p.data() + offs + 3);
|
||||
if (x & 0x40) x |= 0x80; // hfroscrdy = 1 if hfroscen==1
|
||||
} break;
|
||||
case 0x10008008: { // HFROSC base, pllcfg reg
|
||||
mem_type::page_type &p = mem(paddr.val / mem.page_size);
|
||||
size_t offs = paddr.val & mem.page_addr_mask;
|
||||
std::copy(data, data + length, p.data() + offs);
|
||||
uint8_t &x = *(p.data() + offs + 3);
|
||||
x |= 0x80; // set pll lock upon writing
|
||||
} break;
|
||||
default: {
|
||||
mem_type::page_type& p = mem(paddr.val / mem.page_size);
|
||||
std::copy(data, data + length, p.data() + (paddr.val & mem.page_addr_mask));
|
||||
// tohost handling in case of riscv-test
|
||||
if(paddr.access && iss::access_type::FUNC) {
|
||||
auto tohost_upper = (traits<BASE>::XLEN == 32 && paddr.val == (tohost + 4)) ||
|
||||
(traits<BASE>::XLEN == 64 && paddr.val == tohost);
|
||||
auto tohost_lower =
|
||||
(traits<BASE>::XLEN == 32 && paddr.val == tohost) || (traits<BASE>::XLEN == 64 && paddr.val == tohost);
|
||||
auto tohost_upper =
|
||||
(traits<BASE>::XLEN == 32 && paddr.val == (tohost + 4)) || (traits<BASE>::XLEN == 64 && paddr.val == tohost);
|
||||
auto tohost_lower = (traits<BASE>::XLEN == 32 && paddr.val == tohost) || (traits<BASE>::XLEN == 64 && paddr.val == tohost);
|
||||
if(tohost_lower || tohost_upper) {
|
||||
uint64_t hostvar = *reinterpret_cast<uint64_t*>(p.data() + (tohost & mem.page_addr_mask));
|
||||
if(tohost_upper || (tohost_lower && to_host_wr_cnt > 0)) {
|
||||
|
@ -1111,8 +1120,7 @@ iss::status riscv_hart_msu_vp<BASE>::write_mem(phys_addr_t paddr, unsigned lengt
|
|||
}
|
||||
} else if(tohost_lower)
|
||||
to_host_wr_cnt++;
|
||||
} else if ((traits<BASE>::XLEN == 32 && paddr.val == fromhost + 4) ||
|
||||
(traits<BASE>::XLEN == 64 && paddr.val == fromhost)) {
|
||||
} else if((traits<BASE>::XLEN == 32 && paddr.val == fromhost + 4) || (traits<BASE>::XLEN == 64 && paddr.val == fromhost)) {
|
||||
uint64_t fhostvar = *reinterpret_cast<uint64_t*>(p.data() + (fromhost & mem.page_addr_mask));
|
||||
*reinterpret_cast<uint64_t*>(p.data() + (tohost & mem.page_addr_mask)) = fhostvar;
|
||||
}
|
||||
|
@ -1161,13 +1169,13 @@ template <typename BASE> void riscv_hart_msu_vp<BASE>::check_interrupt() {
|
|||
}
|
||||
if(enabled_interrupts != 0) {
|
||||
int res = 0;
|
||||
while ((enabled_interrupts & 1) == 0) enabled_interrupts >>= 1, res++;
|
||||
while((enabled_interrupts & 1) == 0)
|
||||
enabled_interrupts >>= 1, res++;
|
||||
this->reg.pending_trap = res << 16 | 1; // 0x80 << 24 | (cause << 16) | trap_id
|
||||
}
|
||||
}
|
||||
|
||||
template <typename BASE>
|
||||
typename riscv_hart_msu_vp<BASE>::phys_addr_t riscv_hart_msu_vp<BASE>::virt2phys(const iss::addr_t &addr) {
|
||||
template <typename BASE> typename riscv_hart_msu_vp<BASE>::phys_addr_t riscv_hart_msu_vp<BASE>::virt2phys(const iss::addr_t& addr) {
|
||||
const auto type = addr.access & iss::access_type::FUNC;
|
||||
auto it = ptw.find(addr.val >> PGSHIFT);
|
||||
if(it != ptw.end()) {
|
||||
|
@ -1186,8 +1194,8 @@ typename riscv_hart_msu_vp<BASE>::phys_addr_t riscv_hart_msu_vp<BASE>::virt2phys
|
|||
#endif
|
||||
} else {
|
||||
uint32_t mode = type != iss::access_type::FETCH && state.mstatus.MPRV ? // MPRV
|
||||
state.mstatus.MPP :
|
||||
this->reg.PRIV;
|
||||
state.mstatus.MPP
|
||||
: this->reg.PRIV;
|
||||
|
||||
const vm_info& vm = this->vm[static_cast<uint16_t>(type) / 2];
|
||||
|
||||
|
@ -1208,9 +1216,10 @@ typename riscv_hart_msu_vp<BASE>::phys_addr_t riscv_hart_msu_vp<BASE>::virt2phys
|
|||
|
||||
// check that physical address of PTE is legal
|
||||
reg_t pte = 0;
|
||||
const uint8_t res = this->read(iss::address_type::PHYSICAL, addr.access,
|
||||
traits<BASE>::MEM, base + idx * vm.ptesize, vm.ptesize, (uint8_t *)&pte);
|
||||
if (res != 0) throw trap_load_access_fault(addr.val);
|
||||
const uint8_t res = this->read(iss::address_type::PHYSICAL, addr.access, traits<BASE>::MEM, base + idx * vm.ptesize, vm.ptesize,
|
||||
(uint8_t*)&pte);
|
||||
if(res != 0)
|
||||
throw trap_load_access_fault(addr.val);
|
||||
const reg_t ppn = pte >> PTE_PPN_SHIFT;
|
||||
|
||||
if(PTE_TABLE(pte)) { // next level of page table
|
||||
|
@ -1219,10 +1228,9 @@ typename riscv_hart_msu_vp<BASE>::phys_addr_t riscv_hart_msu_vp<BASE>::virt2phys
|
|||
break;
|
||||
} else if(!(pte & PTE_V) || (!(pte & PTE_R) && (pte & PTE_W))) {
|
||||
break;
|
||||
} else if (type == iss::access_type::FETCH
|
||||
? !(pte & PTE_X)
|
||||
} else if(type == (iss::access_type::FETCH ? !(pte & PTE_X)
|
||||
: type == iss::access_type::READ ? !(pte & PTE_R) && !(mxr && (pte & PTE_X))
|
||||
: !((pte & PTE_R) && (pte & PTE_W))) {
|
||||
: !((pte & PTE_R) && (pte & PTE_W)))) {
|
||||
break;
|
||||
} else if((ppn & ((reg_t(1) << ptshift) - 1)) != 0) {
|
||||
break;
|
||||
|
@ -1233,7 +1241,8 @@ typename riscv_hart_msu_vp<BASE>::phys_addr_t riscv_hart_msu_vp<BASE>::virt2phys
|
|||
*(uint32_t*)ppte |= ad;
|
||||
#else
|
||||
// take exception if access or possibly dirty bit is not set.
|
||||
if ((pte & ad) != ad) break;
|
||||
if((pte & ad) != ad)
|
||||
break;
|
||||
#endif
|
||||
// for superpage mappings, make a fake leaf PTE for the TLB's benefit.
|
||||
const reg_t vpn = addr.val >> PGSHIFT;
|
||||
|
@ -1263,9 +1272,12 @@ template <typename BASE> uint64_t riscv_hart_msu_vp<BASE>::enter_trap(uint64_t f
|
|||
auto cur_priv = this->reg.PRIV;
|
||||
// flags are ACTIVE[31:31], CAUSE[30:16], TRAPID[15:0]
|
||||
// calculate and write mcause val
|
||||
if(flags == std::numeric_limits<uint64_t>::max())
|
||||
flags = this->reg.trap_state;
|
||||
auto trap_id = bit_sub<0, 16>(flags);
|
||||
auto cause = bit_sub<16, 15>(flags);
|
||||
if (trap_id == 0 && cause == 11) cause = 0x8 + cur_priv; // adjust environment call cause
|
||||
if(trap_id == 0 && cause == 11)
|
||||
cause = 0x8 + cur_priv; // adjust environment call cause
|
||||
// calculate effective privilege level
|
||||
auto new_priv = PRIV_M;
|
||||
if(trap_id == 0) { // exception
|
||||
|
@ -1341,14 +1353,15 @@ template <typename BASE> uint64_t riscv_hart_msu_vp<BASE>::enter_trap(uint64_t f
|
|||
// calculate addr// set NEXT_PC to trap addressess to jump to based on MODE
|
||||
// bits in mtvec
|
||||
this->reg.NEXT_PC = ivec & ~0x3UL;
|
||||
if ((ivec & 0x1) == 1 && trap_id != 0) this->reg.NEXT_PC += 4 * cause;
|
||||
if((ivec & 0x1) == 1 && trap_id != 0)
|
||||
this->reg.NEXT_PC += 4 * cause;
|
||||
std::array<char, 32> buffer;
|
||||
sprintf(buffer.data(), "0x%016lx", addr);
|
||||
if((flags & 0xffffffff) != 0xffffffff)
|
||||
CLOG(INFO, disass) << (trap_id ? "Interrupt" : "Trap") << " with cause '"
|
||||
<< (trap_id ? irq_str[cause] : trap_str[cause]) << "' (" << cause << ")"
|
||||
<< " at address " << buffer.data() << " occurred, changing privilege level from "
|
||||
<< lvl[cur_priv] << " to " << lvl[new_priv];
|
||||
CLOG(INFO, disass) << (trap_id ? "Interrupt" : "Trap") << " with cause '" << (trap_id ? irq_str[cause] : trap_str[cause]) << "' ("
|
||||
<< cause << ")"
|
||||
<< " at address " << buffer.data() << " occurred, changing privilege level from " << lvl[cur_priv] << " to "
|
||||
<< lvl[new_priv];
|
||||
// reset trap state
|
||||
this->reg.PRIV = new_priv;
|
||||
this->reg.trap_state = 0;
|
||||
|
@ -1391,8 +1404,7 @@ template <typename BASE> uint64_t riscv_hart_msu_vp<BASE>::leave_trap(uint64_t f
|
|||
}
|
||||
// sets the pc to the value stored in the x epc register.
|
||||
this->reg.NEXT_PC = csr[uepc | inst_priv << 8];
|
||||
CLOG(INFO, disass) << "Executing xRET , changing privilege level from " << lvl[cur_priv] << " to "
|
||||
<< lvl[this->reg.PRIV];
|
||||
CLOG(INFO, disass) << "Executing xRET , changing privilege level from " << lvl[cur_priv] << " to " << lvl[this->reg.PRIV];
|
||||
update_vm_info();
|
||||
check_interrupt();
|
||||
return this->reg.NEXT_PC;
|
||||
|
@ -1406,7 +1418,7 @@ template <typename BASE> void riscv_hart_msu_vp<BASE>::wait_until(uint64_t flags
|
|||
this->fault_data = this->reg.PC;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace arch
|
||||
} // namespace iss
|
||||
|
||||
#endif /* _RISCV_HART_MSU_VP_H */
|
File diff suppressed because it is too large
Load Diff
|
@ -30,29 +30,28 @@
|
|||
*
|
||||
*******************************************************************************/
|
||||
|
||||
// clang-format off
|
||||
#include "tgc5c.h"
|
||||
#include "util/ities.h"
|
||||
#include <util/logging.h>
|
||||
#include <iss/arch/tgc_c.h>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <fstream>
|
||||
|
||||
using namespace iss::arch;
|
||||
|
||||
constexpr std::array<const char*, 36> iss::arch::traits<iss::arch::tgc_c>::reg_names;
|
||||
constexpr std::array<const char*, 36> iss::arch::traits<iss::arch::tgc_c>::reg_aliases;
|
||||
constexpr std::array<const uint32_t, 41> iss::arch::traits<iss::arch::tgc_c>::reg_bit_widths;
|
||||
constexpr std::array<const uint32_t, 41> iss::arch::traits<iss::arch::tgc_c>::reg_byte_offsets;
|
||||
constexpr std::array<const char*, 36> iss::arch::traits<iss::arch::tgc5c>::reg_names;
|
||||
constexpr std::array<const char*, 36> iss::arch::traits<iss::arch::tgc5c>::reg_aliases;
|
||||
constexpr std::array<const uint32_t, 43> iss::arch::traits<iss::arch::tgc5c>::reg_bit_widths;
|
||||
constexpr std::array<const uint32_t, 43> iss::arch::traits<iss::arch::tgc5c>::reg_byte_offsets;
|
||||
|
||||
tgc_c::tgc_c() {
|
||||
reg.icount = 0;
|
||||
}
|
||||
tgc5c::tgc5c() = default;
|
||||
|
||||
tgc_c::~tgc_c() = default;
|
||||
tgc5c::~tgc5c() = default;
|
||||
|
||||
void tgc_c::reset(uint64_t address) {
|
||||
auto base_ptr = reinterpret_cast<traits<tgc_c>::reg_t*>(get_regs_base_ptr());
|
||||
for(size_t i=0; i<traits<tgc_c>::NUM_REGS; ++i)
|
||||
void tgc5c::reset(uint64_t address) {
|
||||
auto base_ptr = reinterpret_cast<traits<tgc5c>::reg_t*>(get_regs_base_ptr());
|
||||
for(size_t i=0; i<traits<tgc5c>::NUM_REGS; ++i)
|
||||
*(base_ptr+i)=0;
|
||||
reg.PC=address;
|
||||
reg.NEXT_PC=reg.PC;
|
||||
|
@ -61,11 +60,11 @@ void tgc_c::reset(uint64_t address) {
|
|||
reg.icount=0;
|
||||
}
|
||||
|
||||
uint8_t *tgc_c::get_regs_base_ptr() {
|
||||
uint8_t *tgc5c::get_regs_base_ptr() {
|
||||
return reinterpret_cast<uint8_t*>(®);
|
||||
}
|
||||
|
||||
tgc_c::phys_addr_t tgc_c::virt2phys(const iss::addr_t &pc) {
|
||||
return phys_addr_t(pc); // change logical address to physical address
|
||||
tgc5c::phys_addr_t tgc5c::virt2phys(const iss::addr_t &addr) {
|
||||
return phys_addr_t(addr.access, addr.space, addr.val&traits<tgc5c>::addr_mask);
|
||||
}
|
||||
|
||||
// clang-format on
|
|
@ -30,9 +30,9 @@
|
|||
*
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef _TGC_C_H_
|
||||
#define _TGC_C_H_
|
||||
|
||||
#ifndef _TGC5C_H_
|
||||
#define _TGC5C_H_
|
||||
// clang-format off
|
||||
#include <array>
|
||||
#include <iss/arch/traits.h>
|
||||
#include <iss/arch_if.h>
|
||||
|
@ -41,29 +41,24 @@
|
|||
namespace iss {
|
||||
namespace arch {
|
||||
|
||||
struct tgc_c;
|
||||
struct tgc5c;
|
||||
|
||||
template <> struct traits<tgc_c> {
|
||||
template <> struct traits<tgc5c> {
|
||||
|
||||
constexpr static char const* const core_type = "TGC_C";
|
||||
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"}};
|
||||
{"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"}};
|
||||
{"zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2", "s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6", "pc", "next_pc", "priv", "dpc"}};
|
||||
|
||||
enum constants {MISA_VAL=0b01000000000000000001000100000100, MARCHID_VAL=0x80000003, RFS=32, INSTR_ALIGNMENT=2, XLEN=32, CSR_SIZE=4096, fence=0, fencei=1, fencevmal=2, fencevmau=3, MUL_LEN=64};
|
||||
enum constants {MISA_VAL=1073746180ULL, MARCHID_VAL=2147483651ULL, CLIC_NUM_IRQ=0ULL, XLEN=32ULL, INSTR_ALIGNMENT=2ULL, RFS=32ULL, fence=0ULL, fencei=1ULL, fencevmal=2ULL, fencevmau=3ULL, CSR_SIZE=4096ULL, MUL_LEN=64ULL};
|
||||
|
||||
constexpr static unsigned FP_REGS_SIZE = 0;
|
||||
|
||||
enum reg_e {
|
||||
X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, PC, NEXT_PC, PRIV, DPC, NUM_REGS,
|
||||
TRAP_STATE=NUM_REGS,
|
||||
PENDING_TRAP,
|
||||
ICOUNT,
|
||||
CYCLE,
|
||||
INSTRET
|
||||
X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, PC, NEXT_PC, PRIV, DPC, NUM_REGS, TRAP_STATE=NUM_REGS, PENDING_TRAP, ICOUNT, CYCLE, INSTRET, INSTRUCTION, LAST_BRANCH
|
||||
};
|
||||
|
||||
using reg_t = uint32_t;
|
||||
|
@ -76,19 +71,19 @@ template <> struct traits<tgc_c> {
|
|||
|
||||
using phys_addr_t = iss::typed_addr_t<iss::address_type::PHYSICAL>;
|
||||
|
||||
static constexpr std::array<const uint32_t, 41> reg_bit_widths{
|
||||
{32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,8,32,32,32,64,64,64}};
|
||||
static constexpr std::array<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, 41> reg_byte_offsets{
|
||||
{0,4,8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80,84,88,92,96,100,104,108,112,116,120,124,128,132,136,137,141,145,149,157,165}};
|
||||
static constexpr std::array<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, CSR, FENCE, RES };
|
||||
enum mem_type_e { MEM, FENCE, RES, CSR };
|
||||
|
||||
enum class opcode_e : unsigned short {
|
||||
enum class opcode_e {
|
||||
LUI = 0,
|
||||
AUIPC = 1,
|
||||
JAL = 2,
|
||||
|
@ -129,69 +124,66 @@ template <> struct traits<tgc_c> {
|
|||
FENCE = 37,
|
||||
ECALL = 38,
|
||||
EBREAK = 39,
|
||||
URET = 40,
|
||||
SRET = 41,
|
||||
MRET = 42,
|
||||
WFI = 43,
|
||||
DRET = 44,
|
||||
CSRRW = 45,
|
||||
CSRRS = 46,
|
||||
CSRRC = 47,
|
||||
CSRRWI = 48,
|
||||
CSRRSI = 49,
|
||||
CSRRCI = 50,
|
||||
FENCE_I = 51,
|
||||
MUL = 52,
|
||||
MULH = 53,
|
||||
MULHSU = 54,
|
||||
MULHU = 55,
|
||||
DIV = 56,
|
||||
DIVU = 57,
|
||||
REM = 58,
|
||||
REMU = 59,
|
||||
CADDI4SPN = 60,
|
||||
CLW = 61,
|
||||
CSW = 62,
|
||||
CADDI = 63,
|
||||
CNOP = 64,
|
||||
CJAL = 65,
|
||||
CLI = 66,
|
||||
CLUI = 67,
|
||||
CADDI16SP = 68,
|
||||
__reserved_clui = 69,
|
||||
CSRLI = 70,
|
||||
CSRAI = 71,
|
||||
CANDI = 72,
|
||||
CSUB = 73,
|
||||
CXOR = 74,
|
||||
COR = 75,
|
||||
CAND = 76,
|
||||
CJ = 77,
|
||||
CBEQZ = 78,
|
||||
CBNEZ = 79,
|
||||
CSLLI = 80,
|
||||
CLWSP = 81,
|
||||
CMV = 82,
|
||||
CJR = 83,
|
||||
__reserved_cmv = 84,
|
||||
CADD = 85,
|
||||
CJALR = 86,
|
||||
CEBREAK = 87,
|
||||
CSWSP = 88,
|
||||
DII = 89,
|
||||
MRET = 40,
|
||||
WFI = 41,
|
||||
CSRRW = 42,
|
||||
CSRRS = 43,
|
||||
CSRRC = 44,
|
||||
CSRRWI = 45,
|
||||
CSRRSI = 46,
|
||||
CSRRCI = 47,
|
||||
FENCE_I = 48,
|
||||
MUL = 49,
|
||||
MULH = 50,
|
||||
MULHSU = 51,
|
||||
MULHU = 52,
|
||||
DIV = 53,
|
||||
DIVU = 54,
|
||||
REM = 55,
|
||||
REMU = 56,
|
||||
C__ADDI4SPN = 57,
|
||||
C__LW = 58,
|
||||
C__SW = 59,
|
||||
C__ADDI = 60,
|
||||
C__NOP = 61,
|
||||
C__JAL = 62,
|
||||
C__LI = 63,
|
||||
C__LUI = 64,
|
||||
C__ADDI16SP = 65,
|
||||
__reserved_clui = 66,
|
||||
C__SRLI = 67,
|
||||
C__SRAI = 68,
|
||||
C__ANDI = 69,
|
||||
C__SUB = 70,
|
||||
C__XOR = 71,
|
||||
C__OR = 72,
|
||||
C__AND = 73,
|
||||
C__J = 74,
|
||||
C__BEQZ = 75,
|
||||
C__BNEZ = 76,
|
||||
C__SLLI = 77,
|
||||
C__LWSP = 78,
|
||||
C__MV = 79,
|
||||
C__JR = 80,
|
||||
__reserved_cmv = 81,
|
||||
C__ADD = 82,
|
||||
C__JALR = 83,
|
||||
C__EBREAK = 84,
|
||||
C__SWSP = 85,
|
||||
DII = 86,
|
||||
MAX_OPCODE
|
||||
};
|
||||
};
|
||||
|
||||
struct tgc_c: public arch_if {
|
||||
struct tgc5c: public arch_if {
|
||||
|
||||
using virt_addr_t = typename traits<tgc_c>::virt_addr_t;
|
||||
using phys_addr_t = typename traits<tgc_c>::phys_addr_t;
|
||||
using reg_t = typename traits<tgc_c>::reg_t;
|
||||
using addr_t = typename traits<tgc_c>::addr_t;
|
||||
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;
|
||||
|
||||
tgc_c();
|
||||
~tgc_c();
|
||||
tgc5c();
|
||||
~tgc5c();
|
||||
|
||||
void reset(uint64_t address=0) override;
|
||||
|
||||
|
@ -203,14 +195,6 @@ struct tgc_c: public arch_if {
|
|||
|
||||
inline uint64_t stop_code() { return interrupt_sim; }
|
||||
|
||||
inline phys_addr_t v2p(const iss::addr_t& addr){
|
||||
if (addr.space != traits<tgc_c>::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<tgc_c>::addr_mask);
|
||||
} else
|
||||
return virt2phys(addr);
|
||||
}
|
||||
|
||||
virtual phys_addr_t virt2phys(const iss::addr_t& addr);
|
||||
|
||||
virtual iss::sync_type needed_sync() const { return iss::NO_SYNC; }
|
||||
|
@ -219,7 +203,7 @@ struct tgc_c: public arch_if {
|
|||
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct TGC_C_regs {
|
||||
struct TGC5C_regs {
|
||||
uint32_t X0 = 0;
|
||||
uint32_t X1 = 0;
|
||||
uint32_t X2 = 0;
|
||||
|
@ -258,8 +242,10 @@ struct tgc_c: public arch_if {
|
|||
uint32_t DPC = 0;
|
||||
uint32_t trap_state = 0, pending_trap = 0;
|
||||
uint64_t icount = 0;
|
||||
uint64_t cycle = 0;
|
||||
uint64_t instret = 0;
|
||||
uint32_t last_branch;
|
||||
uint32_t instruction = 0;
|
||||
uint32_t last_branch = 0;
|
||||
} reg;
|
||||
#pragma pack(pop)
|
||||
std::array<address_type, 4> addr_mode;
|
||||
|
@ -273,4 +259,5 @@ struct tgc_c: public arch_if {
|
|||
|
||||
}
|
||||
}
|
||||
#endif /* _TGC_C_H_ */
|
||||
#endif /* _TGC5C_H_ */
|
||||
// clang-format on
|
|
@ -0,0 +1,57 @@
|
|||
#ifndef _ISS_ARCH_TGC_MAPPER_H
|
||||
#define _ISS_ARCH_TGC_MAPPER_H
|
||||
|
||||
#include "riscv_hart_m_p.h"
|
||||
#include "tgc5c.h"
|
||||
using tgc5c_plat_type = iss::arch::riscv_hart_m_p<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
|
|
@ -0,0 +1,171 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (C) 2023 MINRES Technologies GmbH
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Contributors:
|
||||
* eyck@minres.com - initial implementation
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef _RISCV_HART_M_P_WT_CACHE_H
|
||||
#define _RISCV_HART_M_P_WT_CACHE_H
|
||||
|
||||
#include <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 */
|
|
@ -84,8 +84,7 @@ 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 */
|
||||
|
@ -103,8 +102,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;
|
||||
|
||||
|
@ -120,12 +119,11 @@ public:
|
|||
|
||||
status packetsize_query(std::string& out_buf) override;
|
||||
|
||||
status add_break(int type, uint64_t addr, unsigned int length) override;
|
||||
status add_break(break_type type, uint64_t addr, unsigned int length) override;
|
||||
|
||||
status remove_break(int type, uint64_t addr, unsigned int length) override;
|
||||
status remove_break(break_type type, uint64_t addr, unsigned int length) override;
|
||||
|
||||
status resume_from_addr(bool step, int sig, uint64_t addr, rp_thread_ref thread,
|
||||
std::function<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;
|
||||
|
||||
|
@ -158,9 +156,8 @@ 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);
|
||||
|
@ -176,8 +173,7 @@ 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) {
|
||||
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();
|
||||
|
@ -239,8 +235,7 @@ template <typename ARCH> status riscv_target_adapter<ARCH>::write_registers(cons
|
|||
}
|
||||
|
||||
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;
|
||||
|
@ -261,8 +256,7 @@ 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;
|
||||
|
@ -292,21 +286,16 @@ 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) {
|
||||
|
@ -317,8 +306,7 @@ 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);
|
||||
|
@ -331,22 +319,33 @@ template <typename ARCH> status riscv_target_adapter<ARCH>::packetsize_query(std
|
|||
return Ok;
|
||||
}
|
||||
|
||||
template <typename ARCH> status riscv_target_adapter<ARCH>::add_break(int type, uint64_t addr, unsigned int length) {
|
||||
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: {
|
||||
auto saddr = map_addr({iss::access_type::FETCH, iss::address_type::PHYSICAL, 0, addr});
|
||||
auto eaddr = map_addr({iss::access_type::FETCH, iss::address_type::PHYSICAL, 0, addr + length});
|
||||
target_adapter_base::bp_lut.addEntry(++target_adapter_base::bp_count, saddr.val, eaddr.val - saddr.val);
|
||||
LOG(TRACE) << "Adding breakpoint with handle " << target_adapter_base::bp_count << " for addr 0x" << std::hex
|
||||
<< saddr.val << std::dec;
|
||||
LOG(TRACE) << "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(int type, uint64_t addr, unsigned int length) {
|
||||
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: {
|
||||
auto saddr = map_addr({iss::access_type::FETCH, iss::address_type::PHYSICAL, 0, addr});
|
||||
unsigned handle = target_adapter_base::bp_lut.getEntry(saddr.val);
|
||||
if(handle) {
|
||||
LOG(TRACE) << "Removing breakpoint with handle " << handle << " for addr 0x" << std::hex << saddr.val
|
||||
<< std::dec;
|
||||
LOG(TRACE) << "Removing breakpoint with handle " << handle << " for addr 0x" << std::hex << saddr.val << std::dec;
|
||||
// TODO: check length of addr range
|
||||
target_adapter_base::bp_lut.removeEntry(handle);
|
||||
LOG(TRACE) << "Now having " << target_adapter_base::bp_lut.size() << " breakpoints";
|
||||
|
@ -355,6 +354,8 @@ template <typename ARCH> status riscv_target_adapter<ARCH>::remove_break(int typ
|
|||
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,
|
||||
|
@ -454,7 +455,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_ */
|
|
@ -33,15 +33,20 @@
|
|||
#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){
|
||||
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")
|
||||
|
@ -50,13 +55,52 @@ std::tuple<cpu_ptr, vm_ptr> create_cpu(std::string const& backend, unsigned gdb_
|
|||
if(backend == "llvm")
|
||||
return {cpu_ptr{lcpu}, vm_ptr{iss::llvm::create(lcpu, gdb_port)}};
|
||||
#endif
|
||||
#ifdef WITH_LLVM
|
||||
#ifdef WITH_TCC
|
||||
if(backend == "tcc")
|
||||
return {cpu_ptr{lcpu}, vm_ptr{iss::tcc::create(lcpu, gdb_port)}};
|
||||
#endif
|
||||
return {nullptr, nullptr};
|
||||
}
|
||||
|
||||
class core_factory {
|
||||
using cpu_ptr = std::unique_ptr<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_ */
|
|
@ -0,0 +1,8 @@
|
|||
# pctrace
|
||||
|
||||
Trace functionality to allow visualizing coverage in lcov and cachegrind tools. Use environment variables NOCOMPRES and REGDUMP to toggle functionality.
|
||||
- NOCOMPRES: any value turns off the LZ4 compression
|
||||
- REGDUMP: any value switches to tracing the registers instead. Also turns off compression.
|
||||
|
||||
Known Bugs:
|
||||
- currently does not work correctly with jit backends, the plugin cant tell if instructions are compressed. Additionaly the cost of instrs that raise a trap is not known. It takes the cost of the instrid -1 (0 at the moment).
|
|
@ -0,0 +1,114 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (C) 2017 - 2023, MINRES Technologies GmbH
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Contributors:
|
||||
* eyck@minres.com - initial API and implementation
|
||||
******************************************************************************/
|
||||
|
||||
#include "cycle_estimate.h"
|
||||
#include <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) {
|
||||
LOG(ERR) << "Too many root nodes in YAML file " << config_file_name;
|
||||
}
|
||||
for(auto p : root[0]) {
|
||||
auto isa_subset = p.first;
|
||||
auto instructions = p.second;
|
||||
for(auto const& instr : instructions) {
|
||||
auto idx = instr.second["index"].as<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) {
|
||||
LOG(ERR) << "Could not parse input file " << config_file_name << ", reason: " << e.what();
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
LOG(ERR) << "Could not open input file " << config_file_name;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void iss::plugin::cycle_estimate::callback(instr_info_t instr_info) {
|
||||
size_t instr_id = instr_info.instr_id;
|
||||
auto& entry = instr_id < delays.size() ? delays[instr_id] : illegal_desc;
|
||||
if(instr_info.phase_id == PRE_SYNC) {
|
||||
if(entry.f)
|
||||
current_delay = entry.f(instr_if->get_instr_word());
|
||||
} else {
|
||||
if(!entry.f)
|
||||
current_delay = instr_if->is_branch_taken() ? entry.taken : entry.not_taken;
|
||||
if(current_delay > 1)
|
||||
instr_if->update_last_instr_cycles(current_delay);
|
||||
current_delay = 1;
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (C) 2017, 2018, MINRES Technologies GmbH
|
||||
* Copyright (C) 2017 - 2023, MINRES Technologies GmbH
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -37,6 +37,7 @@
|
|||
|
||||
#include "iss/instrumentation_if.h"
|
||||
#include "iss/vm_plugin.h"
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
@ -45,19 +46,14 @@ namespace iss {
|
|||
|
||||
namespace plugin {
|
||||
|
||||
class cycle_estimate: public iss::vm_plugin {
|
||||
BEGIN_BF_DECL(instr_desc, uint32_t)
|
||||
BF_FIELD(taken, 24, 8)
|
||||
BF_FIELD(not_taken, 16, 8)
|
||||
BF_FIELD(is_branch, 8, 8)
|
||||
BF_FIELD(size, 0, 8)
|
||||
instr_desc(uint32_t size, uint32_t taken, uint32_t not_taken, bool branch): instr_desc() {
|
||||
this->size=size;
|
||||
this->taken=taken;
|
||||
this->not_taken=not_taken;
|
||||
this->is_branch=branch;
|
||||
}
|
||||
END_BF_DECL();
|
||||
class cycle_estimate : public vm_plugin {
|
||||
struct instr_desc {
|
||||
size_t size{0};
|
||||
bool is_branch{false};
|
||||
unsigned not_taken{1};
|
||||
unsigned taken{1};
|
||||
std::function<unsigned(uint64_t)> f;
|
||||
};
|
||||
|
||||
public:
|
||||
cycle_estimate() = delete;
|
||||
|
@ -76,13 +72,16 @@ public:
|
|||
|
||||
bool registration(const char* const version, vm_if& arch) override;
|
||||
|
||||
sync_type get_sync() override { return POST_SYNC; };
|
||||
sync_type get_sync() override { return ALL_SYNC; };
|
||||
|
||||
void callback(instr_info_t instr_info, exec_info const&) override;
|
||||
void callback(instr_info_t instr_info) override;
|
||||
|
||||
private:
|
||||
iss::instrumentation_if *arch_instr;
|
||||
iss::instrumentation_if* instr_if{nullptr};
|
||||
uint32_t* reg_base_ptr{nullptr};
|
||||
instr_desc illegal_desc{};
|
||||
std::vector<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;
|
||||
|
@ -92,7 +91,7 @@ private:
|
|||
std::unordered_map<std::pair<uint64_t, uint64_t>, uint64_t, pair_hash> blocks;
|
||||
std::string config_file_name;
|
||||
};
|
||||
}
|
||||
}
|
||||
} // namespace plugin
|
||||
} // namespace iss
|
||||
|
||||
#endif /* _ISS_PLUGIN_CYCLE_ESTIMATE_H_ */
|
|
@ -1,5 +1,5 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (C) 2017, MINRES Technologies GmbH
|
||||
* Copyright (C) 2017 - 2023 MINRES Technologies GmbH
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -32,20 +32,43 @@
|
|||
* eyck@minres.com - initial API and implementation
|
||||
******************************************************************************/
|
||||
|
||||
#include "iss/plugin/instruction_count.h"
|
||||
#include "iss/instrumentation_if.h"
|
||||
#include "instruction_count.h"
|
||||
#include <iss/instrumentation_if.h>
|
||||
#include <yaml-cpp/yaml.h>
|
||||
|
||||
#include <fstream>
|
||||
#include <iss/arch_if.h>
|
||||
#include <util/logging.h>
|
||||
#include <fstream>
|
||||
|
||||
iss::plugin::instruction_count::instruction_count(std::string config_file_name) {
|
||||
if(config_file_name.length() > 0) {
|
||||
std::ifstream is(config_file_name);
|
||||
if(is.is_open()) {
|
||||
try {
|
||||
is >> root;
|
||||
} catch (Json::RuntimeError &e) {
|
||||
auto root = YAML::LoadAll(is);
|
||||
if(root.size() != 1) {
|
||||
LOG(ERR) << "Too many rro nodes in YAML file " << config_file_name;
|
||||
}
|
||||
for(auto p : root[0]) {
|
||||
auto isa_subset = p.first;
|
||||
auto instructions = p.second;
|
||||
for(auto const& instr : instructions) {
|
||||
instr_delay res;
|
||||
res.instr_name = instr.first.as<std::string>();
|
||||
res.size = instr.second["encoding"].as<std::string>().size() - 2; // not counting 0b
|
||||
auto delay = instr.second["delay"];
|
||||
if(delay.IsSequence()) {
|
||||
res.not_taken_delay = delay[0].as<uint64_t>();
|
||||
res.taken_delay = delay[1].as<uint64_t>();
|
||||
} else {
|
||||
res.not_taken_delay = delay.as<uint64_t>();
|
||||
res.taken_delay = res.not_taken_delay;
|
||||
}
|
||||
delays.push_back(std::move(res));
|
||||
}
|
||||
}
|
||||
rep_counts.resize(delays.size());
|
||||
} catch(YAML::ParserException& e) {
|
||||
LOG(ERR) << "Could not parse input file " << config_file_name << ", reason: " << e.what();
|
||||
}
|
||||
} else {
|
||||
|
@ -57,7 +80,7 @@ iss::plugin::instruction_count::instruction_count(std::string config_file_name)
|
|||
iss::plugin::instruction_count::~instruction_count() {
|
||||
size_t idx = 0;
|
||||
for(auto it : delays) {
|
||||
if(rep_counts[idx]>0)
|
||||
if(rep_counts[idx] > 0 && it.instr_name.find("__" != 0))
|
||||
LOG(INFO) << it.instr_name << ";" << rep_counts[idx];
|
||||
idx++;
|
||||
}
|
||||
|
@ -65,31 +88,9 @@ iss::plugin::instruction_count::~instruction_count() {
|
|||
|
||||
bool iss::plugin::instruction_count::registration(const char* const version, vm_if& vm) {
|
||||
auto instr_if = vm.get_arch()->get_instrumentation_if();
|
||||
if(!instr_if) return false;
|
||||
const std::string core_name = instr_if->core_type_name();
|
||||
Json::Value &val = root[core_name];
|
||||
if(!val.isNull() && val.isArray()){
|
||||
delays.reserve(val.size());
|
||||
for(auto it:val){
|
||||
auto name = it["name"];
|
||||
auto size = it["size"];
|
||||
auto delay = it["delay"];
|
||||
if(!name.isString() || !size.isUInt() || !(delay.isUInt() || delay.isArray())) throw std::runtime_error("JSON parse error");
|
||||
if(delay.isUInt()){
|
||||
const instr_delay entry{name.asCString(), size.asUInt(), delay.asUInt(), 0};
|
||||
delays.push_back(entry);
|
||||
} else {
|
||||
const instr_delay entry{name.asCString(), size.asUInt(), delay[0].asUInt(), delay[1].asUInt()};
|
||||
delays.push_back(entry);
|
||||
}
|
||||
}
|
||||
rep_counts.resize(delays.size());
|
||||
} else {
|
||||
LOG(ERR)<<"plugin instruction_count: could not find an entry for "<<core_name<<" in JSON file"<<std::endl;
|
||||
}
|
||||
if(!instr_if)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void iss::plugin::instruction_count::callback(instr_info_t instr_info, exec_info const&) {
|
||||
rep_counts[instr_info.instr_id]++;
|
||||
}
|
||||
void iss::plugin::instruction_count::callback(instr_info_t instr_info) { rep_counts[instr_info.instr_id]++; }
|
|
@ -1,5 +1,5 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (C) 2017, 2018, MINRES Technologies GmbH
|
||||
* Copyright (C) 2017 - 2023, MINRES Technologies GmbH
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -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,14 +69,13 @@ public:
|
|||
|
||||
sync_type get_sync() override { return POST_SYNC; };
|
||||
|
||||
void callback(instr_info_t, exec_info const&) override;
|
||||
void callback(instr_info_t) override;
|
||||
|
||||
private:
|
||||
Json::Value root;
|
||||
std::vector<instr_delay> delays;
|
||||
std::vector<uint64_t> rep_counts;
|
||||
};
|
||||
}
|
||||
}
|
||||
} // namespace plugin
|
||||
} // namespace iss
|
||||
|
||||
#endif /* _ISS_PLUGIN_INSTRUCTION_COUNTER_H_ */
|
127
src/main.cpp
127
src/main.cpp
|
@ -30,20 +30,23 @@
|
|||
*
|
||||
*******************************************************************************/
|
||||
|
||||
#include <array>
|
||||
#include <iostream>
|
||||
#include <iss/factory.h>
|
||||
#include <vector>
|
||||
|
||||
#include "iss/arch/tgc_mapper.h"
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/program_options.hpp>
|
||||
#include <iss/arch/tgc_mapper.h>
|
||||
#ifdef WITH_LLVM
|
||||
#include <iss/llvm/jit_helper.h>
|
||||
#include <iss/llvm/jit_init.h>
|
||||
#endif
|
||||
#include "iss/plugin/cycle_estimate.h"
|
||||
#include "iss/plugin/instruction_count.h"
|
||||
#include <iss/log_categories.h>
|
||||
#include <iss/plugin/cycle_estimate.h>
|
||||
#include <iss/plugin/instruction_count.h>
|
||||
#include <iss/plugin/pctrace.h>
|
||||
#ifndef WIN32
|
||||
#include <iss/plugin/loader.h>
|
||||
#endif
|
||||
#if defined(HAS_LUA)
|
||||
#include <iss/plugin/lua.h>
|
||||
#endif
|
||||
|
@ -59,25 +62,25 @@ int main(int argc, char *argv[]) {
|
|||
// clang-format off
|
||||
desc.add_options()
|
||||
("help,h", "Print help message")
|
||||
("verbose,v", po::value<int>()->implicit_value(0), "Sets logging verbosity")
|
||||
("logfile,f", po::value<std::string>(), "Sets default log file.")
|
||||
("verbose,v", po::value<int>()->default_value(4), "Sets logging verbosity")
|
||||
("logfile,l", po::value<std::string>(), "Sets default log file.")
|
||||
("disass,d", po::value<std::string>()->implicit_value(""), "Enables disassembly")
|
||||
("gdb-port,g", po::value<unsigned>()->default_value(0), "enable gdb server and specify port to use")
|
||||
("instructions,i", po::value<uint64_t>()->default_value(std::numeric_limits<uint64_t>::max()), "max. number of instructions to simulate")
|
||||
("reset,r", po::value<std::string>(), "reset address")
|
||||
("dump-ir", "dump the intermediate representation")
|
||||
("elf", po::value<std::vector<std::string>>(), "ELF file(s) to load")
|
||||
("elf,f", po::value<std::vector<std::string>>(), "ELF file(s) to load")
|
||||
("mem,m", po::value<std::string>(), "the memory input file")
|
||||
("plugin,p", po::value<std::vector<std::string>>(), "plugin to activate")
|
||||
("backend", po::value<std::string>()->default_value("interp"), "the memory input file")
|
||||
("isa", po::value<std::string>()->default_value("tgc_c"), "isa to use for simulation");
|
||||
("backend", po::value<std::string>()->default_value("interp"), "the ISS backend to use, options are: interp, tcc")
|
||||
("isa", po::value<std::string>()->default_value("tgc5c"), "core or isa name to use for simulation, use '?' to get list");
|
||||
// clang-format on
|
||||
auto parsed = po::command_line_parser(argc, argv).options(desc).allow_unregistered().run();
|
||||
try {
|
||||
po::store(parsed, clim); // can throw
|
||||
// --help option
|
||||
if(clim.count("help")) {
|
||||
std::cout << "DBT-RISE-RiscV simulator for RISC-V" << std::endl << desc << std::endl;
|
||||
std::cout << "DBT-RISE-TGC simulator for TGC RISC-V cores" << std::endl << desc << std::endl;
|
||||
return 0;
|
||||
}
|
||||
po::notify(clim); // throws on error, so do after help in case
|
||||
|
@ -91,11 +94,9 @@ int main(int argc, char *argv[]) {
|
|||
|
||||
LOGGER(DEFAULT)::print_time() = false;
|
||||
LOGGER(connection)::print_time() = false;
|
||||
if (clim.count("verbose")) {
|
||||
auto l = logging::as_log_level(clim["verbose"].as<int>());
|
||||
LOGGER(DEFAULT)::reporting_level() = l;
|
||||
LOGGER(connection)::reporting_level() = l;
|
||||
}
|
||||
if(clim.count("logfile")) {
|
||||
// configure the connection logger
|
||||
auto f = fopen(clim["logfile"].as<std::string>().c_str(), "w");
|
||||
|
@ -111,83 +112,68 @@ int main(int argc, char *argv[]) {
|
|||
iss::init_jit_debug(argc, argv);
|
||||
#endif
|
||||
bool dump = clim.count("dump-ir");
|
||||
auto& f = iss::core_factory::instance();
|
||||
// instantiate the simulator
|
||||
iss::vm_ptr vm{nullptr};
|
||||
iss::cpu_ptr cpu{nullptr};
|
||||
std::string isa_opt(clim["isa"].as<std::string>());
|
||||
if (isa_opt == "tgc_c") {
|
||||
std::tie(cpu, vm) =
|
||||
iss::create_cpu<tgc_c_plat_type>(clim["backend"].as<std::string>(), clim["gdb-port"].as<unsigned>());
|
||||
} else
|
||||
#ifdef CORE_TGC_B
|
||||
if (isa_opt == "tgc_b") {
|
||||
std::tie(cpu, vm) =
|
||||
iss::create_cpu<tgc_b_plat_type>(clim["backend"].as<std::string>(), clim["gdb-port"].as<unsigned>());
|
||||
} else
|
||||
#endif
|
||||
#ifdef CORE_TGC_C_XRB_NN
|
||||
if (isa_opt == "tgc_c_xrb_nn") {
|
||||
std::tie(cpu, vm) =
|
||||
iss::create_cpu<tgc_c_xrb_nn_plat_type>(clim["backend"].as<std::string>(), clim["gdb-port"].as<unsigned>());
|
||||
} else
|
||||
#endif
|
||||
#ifdef CORE_TGC_D
|
||||
if (isa_opt == "tgc_d") {
|
||||
std::tie(cpu, vm) =
|
||||
iss::create_cpu<tgc_d_plat_type>(clim["backend"].as<std::string>(), clim["gdb-port"].as<unsigned>());
|
||||
} else
|
||||
#endif
|
||||
#ifdef CORE_TGC_D_XRB_MAC
|
||||
if (isa_opt == "tgc_d_xrb_mac") {
|
||||
std::tie(cpu, vm) =
|
||||
iss::create_cpu<tgc_d_xrb_mac_plat_type>(clim["backend"].as<std::string>(), clim["gdb-port"].as<unsigned>());
|
||||
} else
|
||||
#endif
|
||||
#ifdef CORE_TGC_D_XRB_NN
|
||||
if (isa_opt == "tgc_d_xrb_nn") {
|
||||
std::tie(cpu, vm) =
|
||||
iss::create_cpu<tgc_d_xrb_nn_plat_type>(clim["backend"].as<std::string>(), clim["gdb-port"].as<unsigned>());
|
||||
} else
|
||||
#endif
|
||||
#ifdef CORE_TGC_E
|
||||
if (isa_opt == "tgc_e") {
|
||||
std::tie(cpu, vm) =
|
||||
iss::create_cpu<tgc_e_plat_type>(clim["backend"].as<std::string>(), clim["gdb-port"].as<unsigned>());
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
LOG(ERR) << "Illegal argument value for '--isa': " << isa_opt << std::endl;
|
||||
if(isa_opt.size() == 0 || isa_opt == "?") {
|
||||
auto list = f.get_names();
|
||||
std::sort(std::begin(list), std::end(list));
|
||||
std::cout << "Available implementations (core|platform|backend):\n - " << util::join(list, "\n - ") << std::endl;
|
||||
return 0;
|
||||
} else if(isa_opt.find('|') != std::string::npos) {
|
||||
std::tie(cpu, vm) = f.create(isa_opt + "|" + clim["backend"].as<std::string>(), clim["gdb-port"].as<unsigned>());
|
||||
} else {
|
||||
auto base_isa = isa_opt.substr(0, 5);
|
||||
if(base_isa == "tgc5d" || base_isa == "tgc5e") {
|
||||
isa_opt += "|mu_p_clic_pmp|" + clim["backend"].as<std::string>();
|
||||
} else {
|
||||
isa_opt += "|m_p|" + clim["backend"].as<std::string>();
|
||||
}
|
||||
std::tie(cpu, vm) = f.create(isa_opt, clim["gdb-port"].as<unsigned>());
|
||||
}
|
||||
if(!cpu) {
|
||||
LOG(ERR) << "Could not create cpu for isa " << isa_opt << " and backend " << clim["backend"].as<std::string>() << std::endl;
|
||||
return 127;
|
||||
}
|
||||
if(!vm) {
|
||||
LOG(ERR) << "Could not create vm for isa " << isa_opt << " and backend " << clim["backend"].as<std::string>() << std::endl;
|
||||
return 127;
|
||||
}
|
||||
if(clim.count("plugin")) {
|
||||
for(std::string const& opt_val : clim["plugin"].as<std::vector<std::string>>()) {
|
||||
std::string plugin_name = opt_val;
|
||||
std::string filename{"cycles.txt"};
|
||||
std::string arg{""};
|
||||
std::size_t found = opt_val.find('=');
|
||||
if(found != std::string::npos) {
|
||||
plugin_name = opt_val.substr(0, found);
|
||||
filename = opt_val.substr(found + 1, opt_val.size());
|
||||
arg = opt_val.substr(found + 1, opt_val.size());
|
||||
}
|
||||
#if defined(WITH_PLUGINS)
|
||||
if(plugin_name == "ic") {
|
||||
auto *ic_plugin = new iss::plugin::instruction_count(filename);
|
||||
auto* ic_plugin = new iss::plugin::instruction_count(arg);
|
||||
vm->register_plugin(*ic_plugin);
|
||||
plugin_list.push_back(ic_plugin);
|
||||
} else if(plugin_name == "ce") {
|
||||
auto *ce_plugin = new iss::plugin::cycle_estimate(filename);
|
||||
auto* ce_plugin = new iss::plugin::cycle_estimate(arg);
|
||||
vm->register_plugin(*ce_plugin);
|
||||
plugin_list.push_back(ce_plugin);
|
||||
} else if (plugin_name == "pctrace") {
|
||||
auto *plugin = new iss::plugin::cov(filename);
|
||||
vm->register_plugin(*plugin);
|
||||
plugin_list.push_back(plugin);
|
||||
} else {
|
||||
std::array<char const*, 1> a{{filename.c_str()}};
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
#if !defined(WIN32)
|
||||
std::vector<char const*> a{};
|
||||
if(arg.length())
|
||||
a.push_back({arg.c_str()});
|
||||
iss::plugin::loader l(plugin_name, {{"initPlugin"}});
|
||||
auto* plugin = l.call_function<iss::vm_plugin*>("initPlugin", a.size(), a.data());
|
||||
if(plugin) {
|
||||
vm->register_plugin(*plugin);
|
||||
plugin_list.push_back(plugin);
|
||||
} else {
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
LOG(ERR) << "Unknown plugin name: " << plugin_name << ", valid names are 'ce', 'ic'" << std::endl;
|
||||
return 127;
|
||||
}
|
||||
|
@ -210,11 +196,13 @@ int main(int argc, char *argv[]) {
|
|||
if(clim.count("elf"))
|
||||
for(std::string input : clim["elf"].as<std::vector<std::string>>()) {
|
||||
auto start_addr = vm->get_arch()->load_file(input);
|
||||
if (start_addr.second) start_address = start_addr.first;
|
||||
if(start_addr.second)
|
||||
start_address = start_addr.first;
|
||||
}
|
||||
for(std::string input : args) {
|
||||
auto start_addr = vm->get_arch()->load_file(input); // treat remaining arguments as elf files
|
||||
if (start_addr.second) start_address = start_addr.first;
|
||||
if(start_addr.second)
|
||||
start_address = start_addr.first;
|
||||
}
|
||||
if(clim.count("reset")) {
|
||||
auto str = clim["reset"].as<std::string>();
|
||||
|
@ -224,8 +212,7 @@ int main(int argc, char *argv[]) {
|
|||
auto cycles = clim["instructions"].as<uint64_t>();
|
||||
res = vm->start(cycles, dump);
|
||||
} catch(std::exception& e) {
|
||||
LOG(ERR) << "Unhandled Exception reached the top of main: " << e.what() << ", application will now exit"
|
||||
<< std::endl;
|
||||
LOG(ERR) << "Unhandled Exception reached the top of main: " << e.what() << ", application will now exit" << std::endl;
|
||||
res = 2;
|
||||
}
|
||||
// cleanup to let plugins report of needed
|
||||
|
|
|
@ -1,118 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (C) 2017, MINRES Technologies GmbH
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Contributors:
|
||||
* eyck@minres.com - initial API and implementation
|
||||
******************************************************************************/
|
||||
|
||||
#include "iss/plugin/cycle_estimate.h"
|
||||
|
||||
#include <iss/arch_if.h>
|
||||
#include <util/logging.h>
|
||||
#include <rapidjson/document.h>
|
||||
#include <rapidjson/istreamwrapper.h>
|
||||
#include "rapidjson/writer.h"
|
||||
#include "rapidjson/stringbuffer.h"
|
||||
#include <rapidjson/ostreamwrapper.h>
|
||||
#include <rapidjson/error/en.h>
|
||||
#include <fstream>
|
||||
|
||||
using namespace rapidjson;
|
||||
using namespace std;
|
||||
|
||||
iss::plugin::cycle_estimate::cycle_estimate(string const& config_file_name)
|
||||
: arch_instr(nullptr)
|
||||
, config_file_name(config_file_name)
|
||||
{
|
||||
}
|
||||
|
||||
iss::plugin::cycle_estimate::~cycle_estimate() {
|
||||
}
|
||||
|
||||
bool iss::plugin::cycle_estimate::registration(const char* const version, vm_if& vm) {
|
||||
arch_instr = vm.get_arch()->get_instrumentation_if();
|
||||
if(!arch_instr) return false;
|
||||
const string core_name = arch_instr->core_type_name();
|
||||
if (config_file_name.length() > 0) {
|
||||
ifstream is(config_file_name);
|
||||
if (is.is_open()) {
|
||||
try {
|
||||
IStreamWrapper isw(is);
|
||||
Document d;
|
||||
ParseResult ok = d.ParseStream(isw);
|
||||
if(ok) {
|
||||
Value& val = d[core_name.c_str()];
|
||||
if(val.IsArray()){
|
||||
delays.reserve(val.Size());
|
||||
for (auto it = val.Begin(); it != val.End(); ++it) {
|
||||
auto& name = (*it)["name"];
|
||||
auto& size = (*it)["size"];
|
||||
auto& delay = (*it)["delay"];
|
||||
auto& branch = (*it)["branch"];
|
||||
if(delay.IsArray()) {
|
||||
auto dt = delay[0].Get<unsigned>();
|
||||
auto dnt = delay[1].Get<unsigned>();
|
||||
delays.push_back(instr_desc{size.Get<unsigned>(), dt, dnt, branch.Get<bool>()});
|
||||
} else if(delay.Is<unsigned>()) {
|
||||
auto d = delay.Get<unsigned>();
|
||||
delays.push_back(instr_desc{size.Get<unsigned>(), d, d, branch.Get<bool>()});
|
||||
} else
|
||||
throw runtime_error("JSON parse error");
|
||||
}
|
||||
} else {
|
||||
LOG(ERR)<<"plugin cycle_estimate: could not find an entry for "<<core_name<<" in JSON file"<<endl;
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
LOG(ERR)<<"plugin cycle_estimate: could not parse in JSON file at "<< ok.Offset()<<": "<<GetParseError_En(ok.Code())<<endl;
|
||||
return false;
|
||||
}
|
||||
} catch (runtime_error &e) {
|
||||
LOG(ERR) << "Could not parse input file " << config_file_name << ", reason: " << e.what();
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
LOG(ERR) << "Could not open input file " << config_file_name;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
void iss::plugin::cycle_estimate::callback(instr_info_t instr_info, exec_info const& exc_info) {
|
||||
assert(arch_instr && "No instrumentation interface available but callback executed");
|
||||
auto entry = delays[instr_info.instr_id];
|
||||
bool taken = exc_info.branch_taken;
|
||||
if (exc_info.branch_taken && (entry.taken > 1))
|
||||
arch_instr->set_curr_instr_cycles(entry.taken);
|
||||
else if (entry.not_taken > 1)
|
||||
arch_instr->set_curr_instr_cycles(entry.not_taken);
|
||||
}
|
|
@ -1,133 +0,0 @@
|
|||
#include <iss/arch_if.h>
|
||||
#include <iss/plugin/pctrace.h>
|
||||
#include <util/logging.h>
|
||||
#include <rapidjson/document.h>
|
||||
#include <rapidjson/istreamwrapper.h>
|
||||
#include "rapidjson/writer.h"
|
||||
#include "rapidjson/stringbuffer.h"
|
||||
#include <rapidjson/ostreamwrapper.h>
|
||||
#include <rapidjson/error/en.h>
|
||||
#include <fstream>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
|
||||
using namespace rapidjson;
|
||||
using namespace std;
|
||||
|
||||
iss::plugin::cov::cov(std::string const &filename)
|
||||
: instr_if(nullptr)
|
||||
, filename(filename)
|
||||
{
|
||||
output.open("output.trc");
|
||||
jumped = false;
|
||||
first = true;
|
||||
}
|
||||
|
||||
iss::plugin::cov::~cov() {
|
||||
output.close();
|
||||
}
|
||||
|
||||
bool iss::plugin::cov::registration(const char *const version, vm_if& vm) {
|
||||
instr_if = vm.get_arch()->get_instrumentation_if();
|
||||
if(!instr_if) return false;
|
||||
const string core_name = instr_if->core_type_name();
|
||||
if (filename.length() > 0) {
|
||||
ifstream is(filename);
|
||||
if (is.is_open()) {
|
||||
try {
|
||||
IStreamWrapper isw(is);
|
||||
Document d;
|
||||
ParseResult ok = d.ParseStream(isw);
|
||||
if(ok) {
|
||||
Value& val = d[core_name.c_str()];
|
||||
if(val.IsArray()){
|
||||
delays.reserve(val.Size());
|
||||
for (auto it = val.Begin(); it != val.End(); ++it) {
|
||||
auto& name = (*it)["name"];
|
||||
auto& size = (*it)["size"];
|
||||
auto& delay = (*it)["delay"];
|
||||
auto& branch = (*it)["branch"];
|
||||
if(delay.IsArray()) {
|
||||
auto dt = delay[0].Get<unsigned>();
|
||||
auto dnt = delay[1].Get<unsigned>();
|
||||
delays.push_back(instr_desc{size.Get<unsigned>(), dt, dnt, branch.Get<bool>()});
|
||||
} else if(delay.Is<unsigned>()) {
|
||||
auto d = delay.Get<unsigned>();
|
||||
delays.push_back(instr_desc{size.Get<unsigned>(), d, d, branch.Get<bool>()});
|
||||
} else
|
||||
throw runtime_error("JSON parse error");
|
||||
|
||||
}
|
||||
} else {
|
||||
LOG(ERR)<<"plugin cycle_estimate: could not find an entry for "<<core_name<<" in JSON file"<<endl;
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
LOG(ERR)<<"plugin cycle_estimate: could not parse in JSON file at "<< ok.Offset()<<": "<<GetParseError_En(ok.Code())<<endl;
|
||||
return false;
|
||||
}
|
||||
} catch (runtime_error &e) {
|
||||
LOG(ERR) << "Could not parse input file " << filename << ", reason: " << e.what();
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
LOG(ERR) << "Could not open input file " << filename;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
inline string formatPC(uint64_t pc) {
|
||||
stringstream stream;
|
||||
stream << "0x" << std::hex << pc;
|
||||
return stream.str();
|
||||
}
|
||||
|
||||
void iss::plugin::cov::callback(instr_info_t iinfo, const exec_info& einfo) {
|
||||
// auto delay = 0;
|
||||
// auto entry = delays[iinfo.instr_id];
|
||||
// bool taken = einfo.branch_taken;
|
||||
// if (einfo.branch_taken)
|
||||
// delay = entry.taken;
|
||||
// else
|
||||
// delay = entry.not_taken;
|
||||
//
|
||||
// if (first){
|
||||
// output << formatPC(instr_if->get_pc()) << "," << delay;
|
||||
// first = false;
|
||||
// }
|
||||
// if(instr_if->get_next_pc()-instr_if->get_pc() != delays[iinfo.instr_id].size/8){
|
||||
// //The goal is to keep the output in start-target pairs, so after a jump the target address needs to get written
|
||||
// //to the output. If the target happens to also be a start, we keep the pairing by adding a 0-delay entry.
|
||||
// if (jumped)
|
||||
// output <<"\n" <<formatPC(instr_if->get_pc()) << "," << 0;
|
||||
// output <<"\n" << formatPC(instr_if->get_pc()) << "," << delay;
|
||||
// jumped = true;
|
||||
// }
|
||||
// else{
|
||||
// if (jumped){
|
||||
// output <<"\n" << formatPC(instr_if->get_pc()) << "," << delay;
|
||||
// jumped = false;
|
||||
// }
|
||||
// else if(delay!=1){
|
||||
// output <<"\n" << formatPC(instr_if->get_pc()) << "," << delay;
|
||||
// output <<"\n" << formatPC(instr_if->get_pc()) << "," << 0;
|
||||
// }
|
||||
//
|
||||
// }
|
||||
|
||||
//source code for the full output
|
||||
auto delay = 0;
|
||||
auto entry = delays[iinfo.instr_id];
|
||||
bool taken = einfo.branch_taken;
|
||||
if (einfo.branch_taken)
|
||||
delay = entry.taken;
|
||||
else
|
||||
delay = entry.not_taken;
|
||||
output<<std::hex <<"0x" << instr_if->get_pc() <<"," << delay << "\n";
|
||||
}
|
|
@ -37,23 +37,28 @@
|
|||
#include <iss/debugger/target_adapter_if.h>
|
||||
#include <iss/iss.h>
|
||||
#include <iss/vm_types.h>
|
||||
#include "iss_factory.h"
|
||||
#ifndef WIN32
|
||||
#include <iss/plugin/loader.h>
|
||||
#include <sysc/core_complex.h>
|
||||
#endif
|
||||
#include "sc_core_adapter_if.h"
|
||||
#include <iss/arch/tgc_mapper.h>
|
||||
#include <scc/report.h>
|
||||
#include <util/ities.h>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <array>
|
||||
#include <numeric>
|
||||
#include <iss/plugin/cycle_estimate.h>
|
||||
#include <iss/plugin/instruction_count.h>
|
||||
#include <iss/plugin/pctrace.h>
|
||||
|
||||
// clang-format on
|
||||
|
||||
#define STR(X) #X
|
||||
#define CREATE_CORE(CN) \
|
||||
if (type == STR(CN)) { std::tie(cpu, vm) = create_core<CN ## _plat_type>(backend, gdb_port, hart_id); } else
|
||||
if(type == STR(CN)) { \
|
||||
std::tie(cpu, vm) = create_core<CN##_plat_type>(backend, gdb_port, hart_id); \
|
||||
} else
|
||||
|
||||
#ifdef HAS_SCV
|
||||
#include <scv.h>
|
||||
|
@ -83,137 +88,10 @@ using namespace sc_core;
|
|||
|
||||
namespace {
|
||||
iss::debugger::encoder_decoder encdec;
|
||||
|
||||
std::array<const char, 4> lvl = {{'U', 'S', 'H', 'M'}};
|
||||
}
|
||||
} // namespace
|
||||
|
||||
template<typename PLAT>
|
||||
class core_wrapper_t : public PLAT {
|
||||
public:
|
||||
using reg_t = typename arch::traits<typename PLAT::core>::reg_t;
|
||||
using phys_addr_t = typename arch::traits<typename PLAT::core>::phys_addr_t;
|
||||
using heart_state_t = typename PLAT::hart_state_type;
|
||||
core_wrapper_t(core_complex *owner)
|
||||
: owner(owner) { }
|
||||
|
||||
uint32_t get_mode() { return this->reg.PRIV; }
|
||||
|
||||
inline void set_interrupt_execution(bool v) { this->interrupt_sim = v?1:0; }
|
||||
|
||||
inline bool get_interrupt_execution() { return this->interrupt_sim; }
|
||||
|
||||
heart_state_t &get_state() { return this->state; }
|
||||
|
||||
void notify_phase(iss::arch_if::exec_phase p) override {
|
||||
if (p == iss::arch_if::ISTART) owner->sync(this->reg.icount);
|
||||
}
|
||||
|
||||
sync_type needed_sync() const override { return PRE_SYNC; }
|
||||
|
||||
void disass_output(uint64_t pc, const std::string instr) override {
|
||||
if (!owner->disass_output(pc, instr)) {
|
||||
std::stringstream s;
|
||||
s << "[p:" << lvl[this->reg.PRIV] << ";s:0x" << std::hex << std::setfill('0')
|
||||
<< std::setw(sizeof(reg_t) * 2) << (reg_t)this->state.mstatus << std::dec << ";c:"
|
||||
<< this->reg.icount + this->cycle_offset << "]";
|
||||
SCCDEBUG(owner->name())<<"disass: "
|
||||
<< "0x" << std::setw(16) << std::right << std::setfill('0') << std::hex << pc << "\t\t" << std::setw(40)
|
||||
<< std::setfill(' ') << std::left << instr << s.str();
|
||||
}
|
||||
};
|
||||
|
||||
status read_mem(phys_addr_t addr, unsigned length, uint8_t *const data) override {
|
||||
if (addr.access && access_type::DEBUG)
|
||||
return owner->read_mem_dbg(addr.val, length, data) ? Ok : Err;
|
||||
else {
|
||||
return owner->read_mem(addr.val, length, data, addr.access && access_type::FETCH) ? Ok : Err;
|
||||
}
|
||||
}
|
||||
|
||||
status write_mem(phys_addr_t addr, unsigned length, const uint8_t *const data) override {
|
||||
if (addr.access && access_type::DEBUG)
|
||||
return owner->write_mem_dbg(addr.val, length, data) ? Ok : Err;
|
||||
else {
|
||||
auto res = owner->write_mem(addr.val, length, data) ? Ok : Err;
|
||||
// clear MTIP on mtimecmp write
|
||||
if (addr.val == 0x2004000) {
|
||||
reg_t val;
|
||||
this->read_csr(arch::mip, val);
|
||||
if (val & (1ULL << 7)) this->write_csr(arch::mip, val & ~(1ULL << 7));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
status read_csr(unsigned addr, reg_t &val) override {
|
||||
#ifndef CWR_SYSTEMC
|
||||
if((addr==arch::time || addr==arch::timeh) && owner->mtime_o.get_interface(0)){
|
||||
uint64_t time_val;
|
||||
bool ret = owner->mtime_o->nb_peek(time_val);
|
||||
if (addr == iss::arch::time) {
|
||||
val = static_cast<reg_t>(time_val);
|
||||
} else if (addr == iss::arch::timeh) {
|
||||
if (sizeof(reg_t) != 4) return iss::Err;
|
||||
val = static_cast<reg_t>(time_val >> 32);
|
||||
}
|
||||
return ret?Ok:Err;
|
||||
#else
|
||||
if((addr==arch::time || addr==arch::timeh)){
|
||||
uint64_t time_val = owner->mtime_i.read();
|
||||
if (addr == iss::arch::time) {
|
||||
val = static_cast<reg_t>(time_val);
|
||||
} else if (addr == iss::arch::timeh) {
|
||||
if (sizeof(reg_t) != 4) return iss::Err;
|
||||
val = static_cast<reg_t>(time_val >> 32);
|
||||
}
|
||||
return Ok;
|
||||
#endif
|
||||
} else {
|
||||
return PLAT::read_csr(addr, val);
|
||||
}
|
||||
}
|
||||
|
||||
void wait_until(uint64_t flags) override {
|
||||
SCCDEBUG(owner->name()) << "Sleeping until interrupt";
|
||||
do {
|
||||
sc_core::wait(wfi_evt);
|
||||
} while (this->reg.pending_trap == 0);
|
||||
PLAT::wait_until(flags);
|
||||
}
|
||||
|
||||
void local_irq(short id, bool value) {
|
||||
reg_t mask = 0;
|
||||
switch (id) {
|
||||
case 16: // SW
|
||||
mask = 1 << 3;
|
||||
break;
|
||||
case 17: // timer
|
||||
mask = 1 << 7;
|
||||
break;
|
||||
case 18: // external
|
||||
mask = 1 << 11;
|
||||
break;
|
||||
default:
|
||||
/* do nothing*/
|
||||
break;
|
||||
}
|
||||
if (value) {
|
||||
this->csr[arch::mip] |= mask;
|
||||
wfi_evt.notify();
|
||||
} else
|
||||
this->csr[arch::mip] &= ~mask;
|
||||
this->check_interrupt();
|
||||
if(value)
|
||||
SCCTRACE(owner->name()) << "Triggering interrupt " << id << " Pending trap: " << this->reg.pending_trap;
|
||||
}
|
||||
|
||||
private:
|
||||
core_complex *const owner;
|
||||
sc_event wfi_evt;
|
||||
};
|
||||
|
||||
int cmd_sysc(int argc, char *argv[], debugger::out_func of, debugger::data_func df,
|
||||
debugger::target_adapter_if *tgt_adapter) {
|
||||
int cmd_sysc(int argc, char* argv[], debugger::out_func of, debugger::data_func df, debugger::target_adapter_if* tgt_adapter) {
|
||||
if(argc > 1) {
|
||||
if(strcasecmp(argv[1], "print_time") == 0) {
|
||||
std::string t = sc_time_stamp().to_string();
|
||||
|
@ -247,11 +125,15 @@ using vm_ptr= std::unique_ptr<iss::vm_if>;
|
|||
|
||||
class core_wrapper {
|
||||
public:
|
||||
core_wrapper(core_complex *owner) : owner(owner) { }
|
||||
core_wrapper(core_complex* owner)
|
||||
: owner(owner) {}
|
||||
|
||||
void reset(uint64_t addr) { vm->reset(addr); }
|
||||
inline void start(){vm->start();}
|
||||
inline std::pair<uint64_t, bool> load_file(std::string const& name){ return cpu->load_file(name);};
|
||||
inline void start(bool dump = false) { vm->start(std::numeric_limits<uint64_t>::max(), dump); }
|
||||
inline std::pair<uint64_t, bool> load_file(std::string const& name) {
|
||||
iss::arch_if* cc = cpu->get_arch_if();
|
||||
return cc->load_file(name);
|
||||
};
|
||||
|
||||
std::function<unsigned(void)> get_mode;
|
||||
std::function<uint64_t(void)> get_state;
|
||||
|
@ -259,58 +141,49 @@ public:
|
|||
std::function<void(bool)> set_interrupt_execution;
|
||||
std::function<void(short, bool)> local_irq;
|
||||
|
||||
template<typename PLAT>
|
||||
std::tuple<cpu_ptr, vm_ptr> create_core(std::string const& backend, unsigned gdb_port, uint32_t hart_id){
|
||||
auto* lcpu = new core_wrapper_t<PLAT>(owner);
|
||||
lcpu->set_mhartid(hart_id);
|
||||
get_mode = [lcpu]() { return lcpu->get_mode(); };
|
||||
get_state = [lcpu]() { return lcpu->get_state().mstatus.backing.val; };
|
||||
get_interrupt_execution = [lcpu]() { return lcpu->get_interrupt_execution(); };
|
||||
set_interrupt_execution = [lcpu](bool b) { return lcpu->set_interrupt_execution(b); };
|
||||
local_irq = [lcpu](short s, bool b) { return lcpu->local_irq(s, b); };
|
||||
if(backend == "interp")
|
||||
return {cpu_ptr{lcpu}, vm_ptr{iss::interp::create(static_cast<typename PLAT::core*>(lcpu), gdb_port)}};
|
||||
#ifdef WITH_LLVM
|
||||
if(backend == "llvm")
|
||||
return {cpu_ptr{lcpu}, vm_ptr{iss::llvm::create(lcpu, gdb_port)}};
|
||||
#endif
|
||||
#ifdef WITH_TCC
|
||||
if(backend == "tcc")
|
||||
s return {cpu_ptr{lcpu}, vm_ptr{iss::tcc::create(lcpu, gdb_port)}};
|
||||
#endif
|
||||
return {nullptr, nullptr};
|
||||
}
|
||||
|
||||
void create_cpu(std::string const& type, std::string const& backend, unsigned gdb_port, uint32_t hart_id) {
|
||||
CREATE_CORE(tgc_c)
|
||||
#ifdef CORE_TGC_B
|
||||
CREATE_CORE(tgc_b)
|
||||
#endif
|
||||
#ifdef CORE_TGC_D
|
||||
CREATE_CORE(tgc_d)
|
||||
#endif
|
||||
#ifdef CORE_TGC_D_XRB_MAC
|
||||
CREATE_CORE(tgc_d_xrb_mac)
|
||||
#endif
|
||||
#ifdef CORE_TGC_D_XRB_NN
|
||||
CREATE_CORE(tgc_d_xrb_nn)
|
||||
#endif
|
||||
{
|
||||
LOG(ERR) << "Illegal argument value for core type: " << type << std::endl;
|
||||
auto& f = sysc::iss_factory::instance();
|
||||
if(type.size() == 0 || type == "?") {
|
||||
std::cout << "Available cores: " << util::join(f.get_names(), ", ") << std::endl;
|
||||
sc_core::sc_stop();
|
||||
} else if(type.find('|') != std::string::npos) {
|
||||
std::tie(cpu, vm) = f.create(type + "|" + backend);
|
||||
} else {
|
||||
auto base_isa = type.substr(0, 5);
|
||||
if(base_isa == "tgc5d" || base_isa == "tgc5e") {
|
||||
std::tie(cpu, vm) = f.create(type + "|mu_p_clic_pmp|" + backend, gdb_port, owner);
|
||||
} else {
|
||||
std::tie(cpu, vm) = f.create(type + "|m_p|" + backend, gdb_port, owner);
|
||||
}
|
||||
auto *srv = debugger::server<debugger::gdb_session>::get();
|
||||
if (srv) tgt_adapter = srv->get_target();
|
||||
if (tgt_adapter)
|
||||
tgt_adapter->add_custom_command(
|
||||
{"sysc", [this](int argc, char *argv[], debugger::out_func of,
|
||||
debugger::data_func df) -> int { return cmd_sysc(argc, argv, of, df, tgt_adapter); },
|
||||
"SystemC sub-commands: break <time>, print_time"});
|
||||
}
|
||||
if(!cpu) {
|
||||
SCCFATAL() << "Could not create cpu for isa " << type << " and backend " << backend;
|
||||
}
|
||||
if(!vm) {
|
||||
SCCFATAL() << "Could not create vm for isa " << type << " and backend " << backend;
|
||||
}
|
||||
auto* sc_cpu_if = reinterpret_cast<sc_core_adapter_if*>(cpu.get());
|
||||
sc_cpu_if->set_mhartid(hart_id);
|
||||
get_mode = [sc_cpu_if]() { return sc_cpu_if->get_mode(); };
|
||||
get_state = [sc_cpu_if]() { return sc_cpu_if->get_state(); };
|
||||
get_interrupt_execution = [sc_cpu_if]() { return sc_cpu_if->get_interrupt_execution(); };
|
||||
set_interrupt_execution = [sc_cpu_if](bool b) { return sc_cpu_if->set_interrupt_execution(b); };
|
||||
local_irq = [sc_cpu_if](short s, bool b) { return sc_cpu_if->local_irq(s, b); };
|
||||
|
||||
auto* srv = debugger::server<debugger::gdb_session>::get();
|
||||
if(srv)
|
||||
tgt_adapter = srv->get_target();
|
||||
if(tgt_adapter)
|
||||
tgt_adapter->add_custom_command({"sysc",
|
||||
[this](int argc, char* argv[], debugger::out_func of, debugger::data_func df) -> int {
|
||||
return cmd_sysc(argc, argv, of, df, tgt_adapter);
|
||||
},
|
||||
"SystemC sub-commands: break <time>, print_time"});
|
||||
}
|
||||
|
||||
core_complex* const owner;
|
||||
vm_ptr vm{nullptr};
|
||||
cpu_ptr cpu{nullptr};
|
||||
sc_cpu_ptr cpu{nullptr};
|
||||
iss::debugger::target_adapter_if* tgt_adapter{nullptr};
|
||||
};
|
||||
|
||||
|
@ -328,16 +201,22 @@ SC_HAS_PROCESS(core_complex);// NOLINT
|
|||
#ifndef CWR_SYSTEMC
|
||||
core_complex::core_complex(sc_module_name const& name)
|
||||
: sc_module(name)
|
||||
, fetch_lut(tlm_dmi_ext())
|
||||
, read_lut(tlm_dmi_ext())
|
||||
, write_lut(tlm_dmi_ext())
|
||||
{
|
||||
, write_lut(tlm_dmi_ext()) {
|
||||
init();
|
||||
}
|
||||
#endif
|
||||
|
||||
void core_complex::init() {
|
||||
trc = new core_trace();
|
||||
initiator.register_invalidate_direct_mem_ptr([=](uint64_t start, uint64_t end) -> void {
|
||||
ibus.register_invalidate_direct_mem_ptr([=](uint64_t start, uint64_t end) -> void {
|
||||
auto lut_entry = fetch_lut.getEntry(start);
|
||||
if(lut_entry.get_granted_access() != tlm::tlm_dmi::DMI_ACCESS_NONE && end <= lut_entry.get_end_address() + 1) {
|
||||
fetch_lut.removeEntry(lut_entry);
|
||||
}
|
||||
});
|
||||
dbus.register_invalidate_direct_mem_ptr([=](uint64_t start, uint64_t end) -> void {
|
||||
auto lut_entry = read_lut.getEntry(start);
|
||||
if(lut_entry.get_granted_access() != tlm::tlm_dmi::DMI_ACCESS_NONE && end <= lut_entry.get_end_address() + 1) {
|
||||
read_lut.removeEntry(lut_entry);
|
||||
|
@ -355,8 +234,11 @@ void core_complex::init(){
|
|||
sensitive << sw_irq_i;
|
||||
SC_METHOD(timer_irq_cb);
|
||||
sensitive << timer_irq_i;
|
||||
SC_METHOD(global_irq_cb);
|
||||
sensitive << global_irq_i;
|
||||
SC_METHOD(ext_irq_cb);
|
||||
sensitive << ext_irq_i;
|
||||
SC_METHOD(local_irq_cb);
|
||||
for(auto pin : local_irq_i)
|
||||
sensitive << pin;
|
||||
trc->m_db = scv_tr_db::get_default_db();
|
||||
|
||||
SC_METHOD(forward);
|
||||
|
@ -404,11 +286,8 @@ void core_complex::before_end_of_elaboration() {
|
|||
auto* plugin = new iss::plugin::cycle_estimate(filename);
|
||||
cpu->vm->register_plugin(*plugin);
|
||||
plugin_list.push_back(plugin);
|
||||
} else if (plugin_name == "pctrace") {
|
||||
auto *plugin = new iss::plugin::cov(filename);
|
||||
cpu->vm->register_plugin(*plugin);
|
||||
plugin_list.push_back(plugin);
|
||||
} else {
|
||||
#ifndef WIN32
|
||||
std::array<char const*, 1> a{{filename.c_str()}};
|
||||
iss::plugin::loader l(plugin_name, {{"initPlugin"}});
|
||||
auto* plugin = l.call_function<iss::vm_plugin*>("initPlugin", a.size(), a.data());
|
||||
|
@ -416,15 +295,15 @@ void core_complex::before_end_of_elaboration() {
|
|||
cpu->vm->register_plugin(*plugin);
|
||||
plugin_list.push_back(plugin);
|
||||
} else
|
||||
#endif
|
||||
SCCERR(SCMOD) << "Unknown plugin '" << plugin_name << "' or plugin not found";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void core_complex::start_of_simulation() {
|
||||
quantum_keeper.reset();
|
||||
// quantum_keeper.reset();
|
||||
if(GET_PROP_VALUE(elf_file).size() > 0) {
|
||||
istringstream is(GET_PROP_VALUE(elf_file));
|
||||
string s;
|
||||
|
@ -447,8 +326,10 @@ void core_complex::start_of_simulation() {
|
|||
}
|
||||
|
||||
bool core_complex::disass_output(uint64_t pc, const std::string instr_str) {
|
||||
if (trc->m_db == nullptr) return false;
|
||||
if (trc->tr_handle.is_active()) trc->tr_handle.end_transaction();
|
||||
if(trc->m_db == nullptr)
|
||||
return false;
|
||||
if(trc->tr_handle.is_active())
|
||||
trc->tr_handle.end_transaction();
|
||||
trc->tr_handle = trc->instr_tr_handle->begin_transaction();
|
||||
trc->tr_handle.record_attribute("PC", pc);
|
||||
trc->tr_handle.record_attribute("INSTR", instr_str);
|
||||
|
@ -469,22 +350,33 @@ void core_complex::forward() {
|
|||
|
||||
void core_complex::set_clock_period(sc_core::sc_time period) {
|
||||
curr_clk = period;
|
||||
if (period == SC_ZERO_TIME) cpu->set_interrupt_execution(true);
|
||||
if(period == SC_ZERO_TIME)
|
||||
cpu->set_interrupt_execution(true);
|
||||
}
|
||||
|
||||
void core_complex::rst_cb() {
|
||||
if (rst_i.read()) cpu->set_interrupt_execution(true);
|
||||
if(rst_i.read())
|
||||
cpu->set_interrupt_execution(true);
|
||||
}
|
||||
|
||||
void core_complex::sw_irq_cb() { cpu->local_irq(16, sw_irq_i.read()); }
|
||||
void core_complex::sw_irq_cb() { cpu->local_irq(3, sw_irq_i.read()); }
|
||||
|
||||
void core_complex::timer_irq_cb() { cpu->local_irq(17, timer_irq_i.read()); }
|
||||
void core_complex::timer_irq_cb() { cpu->local_irq(7, timer_irq_i.read()); }
|
||||
|
||||
void core_complex::global_irq_cb() { cpu->local_irq(18, global_irq_i.read()); }
|
||||
void core_complex::ext_irq_cb() { cpu->local_irq(11, ext_irq_i.read()); }
|
||||
|
||||
void core_complex::local_irq_cb() {
|
||||
for(auto i = 0U; i < local_irq_i.size(); ++i) {
|
||||
if(local_irq_i[i].event()) {
|
||||
cpu->local_irq(16 + i, local_irq_i[i].read());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void core_complex::run() {
|
||||
wait(SC_ZERO_TIME); // separate from elaboration phase
|
||||
do {
|
||||
wait(SC_ZERO_TIME);
|
||||
if(rst_i.read()) {
|
||||
cpu->reset(GET_PROP_VALUE(reset_address));
|
||||
wait(rst_i.negedge_event());
|
||||
|
@ -492,21 +384,26 @@ void core_complex::run() {
|
|||
while(curr_clk.read() == SC_ZERO_TIME) {
|
||||
wait(curr_clk.value_changed_event());
|
||||
}
|
||||
quantum_keeper.reset();
|
||||
cpu->set_interrupt_execution(false);
|
||||
cpu->start();
|
||||
cpu->start(dump_ir);
|
||||
} while(cpu->get_interrupt_execution());
|
||||
sc_stop();
|
||||
}
|
||||
|
||||
bool core_complex::read_mem(uint64_t addr, unsigned length, uint8_t* const data, bool is_fetch) {
|
||||
auto lut_entry = read_lut.getEntry(addr);
|
||||
if (lut_entry.get_granted_access() != tlm::tlm_dmi::DMI_ACCESS_NONE &&
|
||||
addr + length <= lut_entry.get_end_address() + 1) {
|
||||
auto& dmi_lut = is_fetch ? fetch_lut : read_lut;
|
||||
auto lut_entry = dmi_lut.getEntry(addr);
|
||||
if(lut_entry.get_granted_access() != tlm::tlm_dmi::DMI_ACCESS_NONE && addr + length <= lut_entry.get_end_address() + 1) {
|
||||
auto offset = addr - lut_entry.get_start_address();
|
||||
std::copy(lut_entry.get_dmi_ptr() + offset, lut_entry.get_dmi_ptr() + offset + length, data);
|
||||
quantum_keeper.inc(lut_entry.get_read_latency());
|
||||
if(is_fetch)
|
||||
ibus_inc += lut_entry.get_read_latency() / curr_clk;
|
||||
else
|
||||
dbus_inc += lut_entry.get_read_latency() / curr_clk;
|
||||
return true;
|
||||
} else {
|
||||
auto& sckt = is_fetch ? ibus : dbus;
|
||||
tlm::tlm_generic_payload gp;
|
||||
gp.set_command(tlm::TLM_READ_COMMAND);
|
||||
gp.set_address(addr);
|
||||
|
@ -521,22 +418,31 @@ bool core_complex::read_mem(uint64_t addr, unsigned length, uint8_t *const data,
|
|||
auto preExt = new tlm::scc::scv::tlm_recording_extension(trc->tr_handle, this);
|
||||
gp.set_extension(preExt);
|
||||
}
|
||||
initiator->b_transport(gp, delay);
|
||||
SCCTRACE(this->name()) << "read_mem(0x" << std::hex << addr << ") : " << data;
|
||||
auto pre_delay = delay;
|
||||
dbus->b_transport(gp, delay);
|
||||
if(pre_delay > delay) {
|
||||
quantum_keeper.reset();
|
||||
} else {
|
||||
auto incr = (delay - quantum_keeper.get_local_time()) / curr_clk;
|
||||
if(is_fetch)
|
||||
ibus_inc += incr;
|
||||
else
|
||||
dbus_inc += incr;
|
||||
}
|
||||
SCCTRACE(this->name()) << "[local time: " << delay << "]: finish read_mem(0x" << std::hex << addr << ") : 0x"
|
||||
<< (length == 4 ? *(uint32_t*)data
|
||||
: length == 2 ? *(uint16_t*)data
|
||||
: (unsigned)*data);
|
||||
if(gp.get_response_status() != tlm::TLM_OK_RESPONSE) {
|
||||
return false;
|
||||
}
|
||||
if (gp.is_dmi_allowed()) {
|
||||
if(gp.is_dmi_allowed() && !GET_PROP_VALUE(disable_dmi)) {
|
||||
gp.set_command(tlm::TLM_READ_COMMAND);
|
||||
gp.set_address(addr);
|
||||
tlm_dmi_ext dmi_data;
|
||||
if (initiator->get_direct_mem_ptr(gp, dmi_data)) {
|
||||
if(sckt->get_direct_mem_ptr(gp, dmi_data)) {
|
||||
if(dmi_data.is_read_allowed())
|
||||
read_lut.addEntry(dmi_data, dmi_data.get_start_address(),
|
||||
dmi_data.get_end_address() - dmi_data.get_start_address() + 1);
|
||||
if (dmi_data.is_write_allowed())
|
||||
write_lut.addEntry(dmi_data, dmi_data.get_start_address(),
|
||||
dmi_data.get_end_address() - dmi_data.get_start_address() + 1);
|
||||
dmi_lut.addEntry(dmi_data, dmi_data.get_start_address(), dmi_data.get_end_address() - dmi_data.get_start_address() + 1);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
@ -545,11 +451,10 @@ bool core_complex::read_mem(uint64_t addr, unsigned length, uint8_t *const data,
|
|||
|
||||
bool core_complex::write_mem(uint64_t addr, unsigned length, const uint8_t* const data) {
|
||||
auto lut_entry = write_lut.getEntry(addr);
|
||||
if (lut_entry.get_granted_access() != tlm::tlm_dmi::DMI_ACCESS_NONE &&
|
||||
addr + length <= lut_entry.get_end_address() + 1) {
|
||||
if(lut_entry.get_granted_access() != tlm::tlm_dmi::DMI_ACCESS_NONE && addr + length <= lut_entry.get_end_address() + 1) {
|
||||
auto offset = addr - lut_entry.get_start_address();
|
||||
std::copy(data, data + length, lut_entry.get_dmi_ptr() + offset);
|
||||
quantum_keeper.inc(lut_entry.get_read_latency());
|
||||
dbus_inc += lut_entry.get_write_latency() / curr_clk;
|
||||
return true;
|
||||
} else {
|
||||
write_buf.resize(length);
|
||||
|
@ -565,20 +470,24 @@ bool core_complex::write_mem(uint64_t addr, unsigned length, const uint8_t *cons
|
|||
auto preExt = new tlm::scc::scv::tlm_recording_extension(trc->tr_handle, this);
|
||||
gp.set_extension(preExt);
|
||||
}
|
||||
initiator->b_transport(gp, delay);
|
||||
quantum_keeper.set(delay);
|
||||
SCCTRACE() << "write_mem(0x" << std::hex << addr << ") : " << data;
|
||||
auto pre_delay = delay;
|
||||
dbus->b_transport(gp, delay);
|
||||
if(pre_delay > delay)
|
||||
quantum_keeper.reset();
|
||||
else
|
||||
dbus_inc += (delay - quantum_keeper.get_local_time()) / curr_clk;
|
||||
SCCTRACE() << "[local time: " << delay << "]: finish write_mem(0x" << std::hex << addr << ") : 0x"
|
||||
<< (length == 4 ? *(uint32_t*)data
|
||||
: length == 2 ? *(uint16_t*)data
|
||||
: (unsigned)*data);
|
||||
if(gp.get_response_status() != tlm::TLM_OK_RESPONSE) {
|
||||
return false;
|
||||
}
|
||||
if (gp.is_dmi_allowed()) {
|
||||
if(gp.is_dmi_allowed() && !GET_PROP_VALUE(disable_dmi)) {
|
||||
gp.set_command(tlm::TLM_READ_COMMAND);
|
||||
gp.set_address(addr);
|
||||
tlm_dmi_ext dmi_data;
|
||||
if (initiator->get_direct_mem_ptr(gp, dmi_data)) {
|
||||
if (dmi_data.is_read_allowed())
|
||||
read_lut.addEntry(dmi_data, dmi_data.get_start_address(),
|
||||
dmi_data.get_end_address() - dmi_data.get_start_address() + 1);
|
||||
if(dbus->get_direct_mem_ptr(gp, dmi_data)) {
|
||||
if(dmi_data.is_write_allowed())
|
||||
write_lut.addEntry(dmi_data, dmi_data.get_start_address(),
|
||||
dmi_data.get_end_address() - dmi_data.get_start_address() + 1);
|
||||
|
@ -589,33 +498,16 @@ bool core_complex::write_mem(uint64_t addr, unsigned length, const uint8_t *cons
|
|||
}
|
||||
|
||||
bool core_complex::read_mem_dbg(uint64_t addr, unsigned length, uint8_t* const data) {
|
||||
auto lut_entry = read_lut.getEntry(addr);
|
||||
if (lut_entry.get_granted_access() != tlm::tlm_dmi::DMI_ACCESS_NONE &&
|
||||
addr + length <= lut_entry.get_end_address() + 1) {
|
||||
auto offset = addr - lut_entry.get_start_address();
|
||||
std::copy(lut_entry.get_dmi_ptr() + offset, lut_entry.get_dmi_ptr() + offset + length, data);
|
||||
quantum_keeper.inc(lut_entry.get_read_latency());
|
||||
return true;
|
||||
} else {
|
||||
tlm::tlm_generic_payload gp;
|
||||
gp.set_command(tlm::TLM_READ_COMMAND);
|
||||
gp.set_address(addr);
|
||||
gp.set_data_ptr(data);
|
||||
gp.set_data_length(length);
|
||||
gp.set_streaming_width(length);
|
||||
return initiator->transport_dbg(gp) == length;
|
||||
}
|
||||
return dbus->transport_dbg(gp) == length;
|
||||
}
|
||||
|
||||
bool core_complex::write_mem_dbg(uint64_t addr, unsigned length, const uint8_t* const data) {
|
||||
auto lut_entry = write_lut.getEntry(addr);
|
||||
if (lut_entry.get_granted_access() != tlm::tlm_dmi::DMI_ACCESS_NONE &&
|
||||
addr + length <= lut_entry.get_end_address() + 1) {
|
||||
auto offset = addr - lut_entry.get_start_address();
|
||||
std::copy(data, data + length, lut_entry.get_dmi_ptr() + offset);
|
||||
quantum_keeper.inc(lut_entry.get_read_latency());
|
||||
return true;
|
||||
} else {
|
||||
write_buf.resize(length);
|
||||
std::copy(data, data + length, write_buf.begin()); // need to copy as TLM does not guarantee data integrity
|
||||
tlm::tlm_generic_payload gp;
|
||||
|
@ -624,8 +516,7 @@ bool core_complex::write_mem_dbg(uint64_t addr, unsigned length, const uint8_t *
|
|||
gp.set_data_ptr(write_buf.data());
|
||||
gp.set_data_length(length);
|
||||
gp.set_streaming_width(length);
|
||||
return initiator->transport_dbg(gp) == length;
|
||||
return dbus->transport_dbg(gp) == length;
|
||||
}
|
||||
}
|
||||
} /* namespace SiFive */
|
||||
} /* namespace tgfs */
|
||||
} /* namespace sysc */
|
||||
|
|
|
@ -33,20 +33,22 @@
|
|||
#ifndef _SYSC_CORE_COMPLEX_H_
|
||||
#define _SYSC_CORE_COMPLEX_H_
|
||||
|
||||
#include <tlm/scc/initiator_mixin.h>
|
||||
#include <scc/traceable.h>
|
||||
#include <scc/tick2time.h>
|
||||
#include <scc/traceable.h>
|
||||
#include <scc/utilities.h>
|
||||
#include <tlm/scc/initiator_mixin.h>
|
||||
#include <tlm/scc/scv/tlm_rec_initiator_socket.h>
|
||||
#ifdef CWR_SYSTEMC
|
||||
#include <scmlinc/scml_property.h>
|
||||
#define SOCKET_WIDTH 32
|
||||
#else
|
||||
#include <cci_configuration>
|
||||
#define SOCKET_WIDTH scc::LT
|
||||
#endif
|
||||
#include <memory>
|
||||
#include <tlm>
|
||||
#include <tlm_utils/tlm_quantumkeeper.h>
|
||||
#include <util/range_lut.h>
|
||||
#include <memory>
|
||||
|
||||
namespace iss {
|
||||
class vm_plugin;
|
||||
|
@ -56,8 +58,8 @@ 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();
|
||||
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); }
|
||||
|
@ -69,11 +71,13 @@ struct core_trace;
|
|||
|
||||
class core_complex : public sc_core::sc_module, public scc::traceable {
|
||||
public:
|
||||
tlm::scc::initiator_mixin<tlm::scc::scv::tlm_rec_initiator_socket<32>> initiator{"intor"};
|
||||
tlm::scc::initiator_mixin<tlm::tlm_initiator_socket<SOCKET_WIDTH>> ibus{"ibus"};
|
||||
|
||||
tlm::scc::initiator_mixin<tlm::tlm_initiator_socket<SOCKET_WIDTH>> dbus{"dbus"};
|
||||
|
||||
sc_core::sc_in<bool> rst_i{"rst_i"};
|
||||
|
||||
sc_core::sc_in<bool> global_irq_i{"global_irq_i"};
|
||||
sc_core::sc_in<bool> ext_irq_i{"ext_irq_i"};
|
||||
|
||||
sc_core::sc_in<bool> timer_irq_i{"timer_irq_i"};
|
||||
|
||||
|
@ -84,15 +88,17 @@ public:
|
|||
#ifndef CWR_SYSTEMC
|
||||
sc_core::sc_in<sc_core::sc_time> clk_i{"clk_i"};
|
||||
|
||||
sc_core::sc_port<tlm::tlm_peek_if<uint64_t>, 1, sc_core::SC_ZERO_OR_MORE_BOUND> mtime_o;
|
||||
sc_core::sc_port<tlm::tlm_peek_if<uint64_t>, 1, sc_core::SC_ZERO_OR_MORE_BOUND> mtime_o{"mtime_o"};
|
||||
|
||||
cci::cci_param<std::string> elf_file{"elf_file", ""};
|
||||
|
||||
cci::cci_param<bool> enable_disass{"enable_disass", false};
|
||||
|
||||
cci::cci_param<bool> disable_dmi{"disable_dmi", false};
|
||||
|
||||
cci::cci_param<uint64_t> reset_address{"reset_address", 0ULL};
|
||||
|
||||
cci::cci_param<std::string> core_type{"core_type", "tgc_c"};
|
||||
cci::cci_param<std::string> core_type{"core_type", "tgc5c"};
|
||||
|
||||
cci::cci_param<std::string> backend{"backend", "interp"};
|
||||
|
||||
|
@ -115,9 +121,11 @@ public:
|
|||
|
||||
scml_property<bool> enable_disass{"enable_disass", false};
|
||||
|
||||
scml_property<bool> disable_dmi{"disable_dmi", false};
|
||||
|
||||
scml_property<unsigned long long> reset_address{"reset_address", 0ULL};
|
||||
|
||||
scml_property<std::string> core_type{"core_type", "tgc_c"};
|
||||
scml_property<std::string> core_type{"core_type", "tgc5c"};
|
||||
|
||||
scml_property<std::string> backend{"backend", "interp"};
|
||||
|
||||
|
@ -135,14 +143,15 @@ public:
|
|||
, elf_file{"elf_file", ""}
|
||||
, enable_disass{"enable_disass", false}
|
||||
, reset_address{"reset_address", 0ULL}
|
||||
, core_type{"core_type", "tgc_c"}
|
||||
, core_type{"core_type", "tgc5c"}
|
||||
, backend{"backend", "interp"}
|
||||
, gdb_server_port{"gdb_server_port", 0}
|
||||
, dump_ir{"dump_ir", false}
|
||||
, mhartid{"mhartid", 0}
|
||||
, plugins{"plugins", ""}
|
||||
, fetch_lut(tlm_dmi_ext())
|
||||
, read_lut(tlm_dmi_ext())
|
||||
, write_lut(tlm_dmi_ext())
|
||||
{
|
||||
, write_lut(tlm_dmi_ext()) {
|
||||
init();
|
||||
}
|
||||
|
||||
|
@ -150,9 +159,15 @@ public:
|
|||
|
||||
~core_complex();
|
||||
|
||||
inline unsigned get_last_bus_cycles() {
|
||||
auto mem_incr = std::max(ibus_inc, dbus_inc);
|
||||
ibus_inc = dbus_inc = 0;
|
||||
return mem_incr > 1 ? mem_incr : 1;
|
||||
}
|
||||
|
||||
inline void sync(uint64_t cycle) {
|
||||
auto time = curr_clk * (cycle - last_sync_cycle);
|
||||
quantum_keeper.inc(time);
|
||||
auto core_inc = curr_clk * (cycle - last_sync_cycle);
|
||||
quantum_keeper.inc(core_inc);
|
||||
if(quantum_keeper.need_sync()) {
|
||||
wait(quantum_keeper.get_local_time());
|
||||
quantum_keeper.reset();
|
||||
|
@ -173,6 +188,7 @@ public:
|
|||
bool disass_output(uint64_t pc, const std::string instr);
|
||||
|
||||
void set_clock_period(sc_core::sc_time period);
|
||||
|
||||
protected:
|
||||
void before_end_of_elaboration() override;
|
||||
void start_of_simulation() override;
|
||||
|
@ -181,21 +197,23 @@ protected:
|
|||
void rst_cb();
|
||||
void sw_irq_cb();
|
||||
void timer_irq_cb();
|
||||
void global_irq_cb();
|
||||
void ext_irq_cb();
|
||||
void local_irq_cb();
|
||||
uint64_t last_sync_cycle = 0;
|
||||
util::range_lut<tlm_dmi_ext> read_lut, write_lut;
|
||||
util::range_lut<tlm_dmi_ext> fetch_lut, read_lut, write_lut;
|
||||
tlm_utils::tlm_quantumkeeper quantum_keeper;
|
||||
std::vector<uint8_t> write_buf;
|
||||
core_wrapper* cpu{nullptr};
|
||||
sc_core::sc_signal<sc_core::sc_time> curr_clk;
|
||||
uint64_t ibus_inc{0}, dbus_inc{0};
|
||||
core_trace* trc{nullptr};
|
||||
std::unique_ptr<scc::tick2time> t2t;
|
||||
|
||||
private:
|
||||
void init();
|
||||
std::vector<iss::vm_plugin*> plugin_list;
|
||||
|
||||
};
|
||||
} /* namespace SiFive */
|
||||
} /* namespace tgfs */
|
||||
} /* namespace sysc */
|
||||
|
||||
#endif /* _SYSC_CORE_COMPLEX_H_ */
|
|
@ -1,5 +1,5 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (C) 2017, 2018, MINRES Technologies GmbH
|
||||
* Copyright (C) 2021 MINRES Technologies GmbH
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -28,72 +28,63 @@
|
|||
* 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
|
||||
******************************************************************************/
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef _ISS_PLUGIN_COV_H_
|
||||
#define _ISS_PLUGIN_COV_H_
|
||||
#ifndef _ISS_FACTORY_H_
|
||||
#define _ISS_FACTORY_H_
|
||||
|
||||
#include <iss/vm_plugin.h>
|
||||
#include "iss/instrumentation_if.h"
|
||||
#include <json/json.h>
|
||||
#include "sc_core_adapter_if.h"
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <iss/iss.h>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
namespace sysc {
|
||||
|
||||
namespace iss {
|
||||
namespace plugin {
|
||||
|
||||
class cov : public iss::vm_plugin {
|
||||
struct instr_delay {
|
||||
std::string instr_name;
|
||||
size_t size;
|
||||
size_t not_taken_delay;
|
||||
size_t taken_delay;
|
||||
};
|
||||
BEGIN_BF_DECL(instr_desc, uint32_t)
|
||||
BF_FIELD(taken, 24, 8)
|
||||
BF_FIELD(not_taken, 16, 8)
|
||||
BF_FIELD(is_branch, 8, 8)
|
||||
BF_FIELD(size, 0, 8)
|
||||
instr_desc(uint32_t size, uint32_t taken, uint32_t not_taken, bool branch): instr_desc() {
|
||||
this->size=size;
|
||||
this->taken=taken;
|
||||
this->not_taken=not_taken;
|
||||
this->is_branch=branch;
|
||||
}
|
||||
END_BF_DECL();
|
||||
using sc_cpu_ptr = std::unique_ptr<sc_core_adapter_if>;
|
||||
using vm_ptr = std::unique_ptr<iss::vm_if>;
|
||||
|
||||
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>;
|
||||
|
||||
cov(const cov &) = delete;
|
||||
iss_factory() = default;
|
||||
iss_factory(const iss_factory&) = delete;
|
||||
iss_factory& operator=(const iss_factory&) = delete;
|
||||
|
||||
cov(const cov &&) = delete;
|
||||
static iss_factory& instance() {
|
||||
static iss_factory bf;
|
||||
return bf;
|
||||
}
|
||||
|
||||
cov(std::string const &);
|
||||
bool register_creator(const std::string& className, create_fn const& fn) {
|
||||
registry[className] = fn;
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual ~cov();
|
||||
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};
|
||||
}
|
||||
|
||||
cov &operator=(const cov &) = delete;
|
||||
|
||||
cov &operator=(const cov &&) = delete;
|
||||
|
||||
bool registration(const char *const version, vm_if &arch) override;
|
||||
|
||||
sync_type get_sync() override { return POST_SYNC; };
|
||||
|
||||
void callback(instr_info_t, exec_info const&) override;
|
||||
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;
|
||||
}
|
||||
|
||||
private:
|
||||
iss::instrumentation_if *instr_if {nullptr};
|
||||
std::ofstream output;
|
||||
std::string filename;
|
||||
std::vector<instr_desc> delays;
|
||||
bool jumped, first;
|
||||
|
||||
registry_t registry;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* _ISS_PLUGIN_COV_H_ */
|
||||
} // namespace sysc
|
||||
|
||||
#endif /* _ISS_FACTORY_H_ */
|
|
@ -0,0 +1,110 @@
|
|||
/*******************************************************************************
|
||||
* 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 "iss_factory.h"
|
||||
#include <iss/arch/tgc5c.h>
|
||||
#include <iss/arch/riscv_hart_m_p.h>
|
||||
#include <iss/arch/riscv_hart_mu_p.h>
|
||||
#include "sc_core_adapter.h"
|
||||
#include "core_complex.h"
|
||||
#include <array>
|
||||
// clang-format on
|
||||
|
||||
namespace iss {
|
||||
namespace interp {
|
||||
using namespace sysc;
|
||||
volatile std::array<bool, 2> tgc_init = {
|
||||
iss_factory::instance().register_creator("tgc5c|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::tgc5c>>(cc);
|
||||
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::tgc5c*>(cpu), gdb_port)}};
|
||||
}),
|
||||
iss_factory::instance().register_creator("tgc5c|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::tgc5c>>(cc);
|
||||
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::tgc5c*>(cpu), gdb_port)}};
|
||||
})};
|
||||
} // namespace interp
|
||||
#if defined(WITH_LLVM)
|
||||
namespace llvm {
|
||||
using namespace sysc;
|
||||
volatile std::array<bool, 2> tgc_init = {
|
||||
iss_factory::instance().register_creator("tgc5c|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::tgc5c>>(cc);
|
||||
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::tgc5c*>(cpu), gdb_port)}};
|
||||
}),
|
||||
iss_factory::instance().register_creator("tgc5c|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::tgc5c>>(cc);
|
||||
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::tgc5c*>(cpu), gdb_port)}};
|
||||
})};
|
||||
} // namespace llvm
|
||||
#endif
|
||||
#if defined(WITH_TCC)
|
||||
namespace tcc {
|
||||
using namespace sysc;
|
||||
volatile std::array<bool, 2> tgc_init = {
|
||||
iss_factory::instance().register_creator("tgc5c|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::tgc5c>>(cc);
|
||||
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::tgc5c*>(cpu), gdb_port)}};
|
||||
}),
|
||||
iss_factory::instance().register_creator("tgc5c|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::tgc5c>>(cc);
|
||||
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::tgc5c*>(cpu), gdb_port)}};
|
||||
})};
|
||||
} // namespace tcc
|
||||
#endif
|
||||
#if defined(WITH_ASMJIT)
|
||||
namespace asmjit {
|
||||
using namespace sysc;
|
||||
volatile std::array<bool, 2> tgc_init = {
|
||||
iss_factory::instance().register_creator("tgc5c|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::tgc5c>>(cc);
|
||||
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::tgc5c*>(cpu), gdb_port)}};
|
||||
}),
|
||||
iss_factory::instance().register_creator("tgc5c|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::tgc5c>>(cc);
|
||||
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::tgc5c*>(cpu), gdb_port)}};
|
||||
})};
|
||||
} // namespace asmjit
|
||||
#endif
|
||||
} // namespace iss
|
|
@ -0,0 +1,187 @@
|
|||
/*
|
||||
* sc_core_adapter.h
|
||||
*
|
||||
* Created on: Jul 5, 2023
|
||||
* Author: eyck
|
||||
*/
|
||||
|
||||
#ifndef _SYSC_SC_CORE_ADAPTER_H_
|
||||
#define _SYSC_SC_CORE_ADAPTER_H_
|
||||
|
||||
#include "sc_core_adapter_if.h"
|
||||
#include <iostream>
|
||||
#include <iss/iss.h>
|
||||
#include <iss/vm_types.h>
|
||||
#include <scc/report.h>
|
||||
#include <util/ities.h>
|
||||
|
||||
namespace sysc {
|
||||
template <typename PLAT> class sc_core_adapter : public PLAT, public sc_core_adapter_if {
|
||||
public:
|
||||
using reg_t = typename iss::arch::traits<typename PLAT::core>::reg_t;
|
||||
using phys_addr_t = typename iss::arch::traits<typename PLAT::core>::phys_addr_t;
|
||||
using heart_state_t = typename PLAT::hart_state_type;
|
||||
sc_core_adapter(sysc::tgfs::core_complex* owner)
|
||||
: owner(owner) {}
|
||||
|
||||
iss::arch_if* get_arch_if() override { return this; }
|
||||
|
||||
void set_mhartid(unsigned id) override { PLAT::set_mhartid(id); }
|
||||
|
||||
uint32_t get_mode() override { return this->reg.PRIV; }
|
||||
|
||||
void set_interrupt_execution(bool v) override { this->interrupt_sim = v ? 1 : 0; }
|
||||
|
||||
bool get_interrupt_execution() override { return this->interrupt_sim; }
|
||||
|
||||
uint64_t get_state() override { return this->state.mstatus.backing.val; }
|
||||
|
||||
void notify_phase(iss::arch_if::exec_phase p) override {
|
||||
if(p == iss::arch_if::ISTART && !first) {
|
||||
auto cycle_incr = owner->get_last_bus_cycles();
|
||||
if(cycle_incr > 1)
|
||||
this->instr_if.update_last_instr_cycles(cycle_incr);
|
||||
owner->sync(this->instr_if.get_total_cycles());
|
||||
}
|
||||
first = false;
|
||||
}
|
||||
|
||||
iss::sync_type needed_sync() const override { return iss::PRE_SYNC; }
|
||||
|
||||
void disass_output(uint64_t pc, const std::string instr) override {
|
||||
static constexpr std::array<const char, 4> lvl = {{'U', 'S', 'H', 'M'}};
|
||||
if(!owner->disass_output(pc, instr)) {
|
||||
std::stringstream s;
|
||||
s << "[p:" << lvl[this->reg.PRIV] << ";s:0x" << std::hex << std::setfill('0') << std::setw(sizeof(reg_t) * 2)
|
||||
<< (reg_t)this->state.mstatus << std::dec << ";c:" << this->reg.icount + this->cycle_offset << "]";
|
||||
SCCDEBUG(owner->name()) << "disass: "
|
||||
<< "0x" << std::setw(16) << std::right << std::setfill('0') << std::hex << pc << "\t\t" << std::setw(40)
|
||||
<< std::setfill(' ') << std::left << instr << s.str();
|
||||
}
|
||||
};
|
||||
|
||||
iss::status read_mem(phys_addr_t addr, unsigned length, uint8_t* const data) override {
|
||||
if(addr.access && iss::access_type::DEBUG)
|
||||
return owner->read_mem_dbg(addr.val, length, data) ? iss::Ok : iss::Err;
|
||||
else {
|
||||
return owner->read_mem(addr.val, length, data, is_fetch(addr.access)) ? iss::Ok : iss::Err;
|
||||
}
|
||||
}
|
||||
|
||||
iss::status write_mem(phys_addr_t addr, unsigned length, const uint8_t* const data) override {
|
||||
if(addr.access && iss::access_type::DEBUG)
|
||||
return owner->write_mem_dbg(addr.val, length, data) ? iss::Ok : iss::Err;
|
||||
else {
|
||||
auto tohost_upper = (sizeof(reg_t) == 4 && addr.val == (this->tohost + 4)) || (sizeof(reg_t) == 8 && addr.val == this->tohost);
|
||||
auto tohost_lower = (sizeof(reg_t) == 4 && addr.val == this->tohost) || (sizeof(reg_t) == 64 && addr.val == this->tohost);
|
||||
if(tohost_lower || tohost_upper) {
|
||||
if(tohost_upper || (tohost_lower && to_host_wr_cnt > 0)) {
|
||||
switch(hostvar >> 48) {
|
||||
case 0:
|
||||
if(hostvar != 0x1) {
|
||||
SCCINFO(owner->name())
|
||||
<< "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar << "), stopping simulation";
|
||||
} else {
|
||||
SCCINFO(owner->name())
|
||||
<< "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar << "), stopping simulation";
|
||||
}
|
||||
this->reg.trap_state = std::numeric_limits<uint32_t>::max();
|
||||
this->interrupt_sim = hostvar;
|
||||
#ifndef WITH_TCC
|
||||
throw(iss::simulation_stopped(hostvar));
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if(tohost_lower)
|
||||
to_host_wr_cnt++;
|
||||
return iss::Ok;
|
||||
} else {
|
||||
auto res = owner->write_mem(addr.val, length, data) ? iss::Ok : iss::Err;
|
||||
// clear MTIP on mtimecmp write
|
||||
if(addr.val == 0x2004000) {
|
||||
reg_t val;
|
||||
this->read_csr(iss::arch::mip, val);
|
||||
if(val & (1ULL << 7))
|
||||
this->write_csr(iss::arch::mip, val & ~(1ULL << 7));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
iss::status read_csr(unsigned addr, reg_t& val) override {
|
||||
#ifndef CWR_SYSTEMC
|
||||
if((addr == iss::arch::time || addr == iss::arch::timeh) && owner->mtime_o.get_interface(0)) {
|
||||
uint64_t time_val;
|
||||
bool ret = owner->mtime_o->nb_peek(time_val);
|
||||
if(addr == iss::arch::time) {
|
||||
val = static_cast<reg_t>(time_val);
|
||||
} else if(addr == iss::arch::timeh) {
|
||||
if(sizeof(reg_t) != 4)
|
||||
return iss::Err;
|
||||
val = static_cast<reg_t>(time_val >> 32);
|
||||
}
|
||||
return ret ? iss::Ok : iss::Err;
|
||||
#else
|
||||
if((addr == iss::arch::time || addr == iss::arch::timeh)) {
|
||||
uint64_t time_val = owner->mtime_i.read();
|
||||
if(addr == iss::arch::time) {
|
||||
val = static_cast<reg_t>(time_val);
|
||||
} else if(addr == iss::arch::timeh) {
|
||||
if(sizeof(reg_t) != 4)
|
||||
return iss::Err;
|
||||
val = static_cast<reg_t>(time_val >> 32);
|
||||
}
|
||||
return iss::Ok;
|
||||
#endif
|
||||
} else {
|
||||
return PLAT::read_csr(addr, val);
|
||||
}
|
||||
}
|
||||
|
||||
void wait_until(uint64_t flags) override {
|
||||
SCCDEBUG(owner->name()) << "Sleeping until interrupt";
|
||||
while(this->reg.pending_trap == 0 && (this->csr[iss::arch::mip] & this->csr[iss::arch::mie]) == 0) {
|
||||
sc_core::wait(wfi_evt);
|
||||
}
|
||||
PLAT::wait_until(flags);
|
||||
}
|
||||
|
||||
void local_irq(short id, bool value) override {
|
||||
reg_t mask = 0;
|
||||
switch(id) {
|
||||
case 3: // SW
|
||||
mask = 1 << 3;
|
||||
break;
|
||||
case 7: // timer
|
||||
mask = 1 << 7;
|
||||
break;
|
||||
case 11: // external
|
||||
mask = 1 << 11;
|
||||
break;
|
||||
default:
|
||||
if(id > 15)
|
||||
mask = 1 << id;
|
||||
break;
|
||||
}
|
||||
if(value) {
|
||||
this->csr[iss::arch::mip] |= mask;
|
||||
wfi_evt.notify();
|
||||
} else
|
||||
this->csr[iss::arch::mip] &= ~mask;
|
||||
this->check_interrupt();
|
||||
if(value)
|
||||
SCCTRACE(owner->name()) << "Triggering interrupt " << id << " Pending trap: " << this->reg.pending_trap;
|
||||
}
|
||||
|
||||
private:
|
||||
sysc::tgfs::core_complex* const owner;
|
||||
sc_core::sc_event wfi_evt;
|
||||
uint64_t hostvar{std::numeric_limits<uint64_t>::max()};
|
||||
unsigned to_host_wr_cnt = 0;
|
||||
bool first{true};
|
||||
};
|
||||
} // namespace sysc
|
||||
#endif /* _SYSC_SC_CORE_ADAPTER_H_ */
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* sc_core_adapter.h
|
||||
*
|
||||
* Created on: Jul 5, 2023
|
||||
* Author: eyck
|
||||
*/
|
||||
|
||||
#ifndef _SYSC_SC_CORE_ADAPTER_IF_H_
|
||||
#define _SYSC_SC_CORE_ADAPTER_IF_H_
|
||||
|
||||
#include "core_complex.h"
|
||||
#include <iostream>
|
||||
#include <iss/iss.h>
|
||||
#include <iss/vm_types.h>
|
||||
#include <scc/report.h>
|
||||
#include <util/ities.h>
|
||||
|
||||
namespace sysc {
|
||||
struct sc_core_adapter_if {
|
||||
virtual iss::arch_if* get_arch_if() = 0;
|
||||
virtual void set_mhartid(unsigned) = 0;
|
||||
virtual uint32_t get_mode() = 0;
|
||||
virtual uint64_t get_state() = 0;
|
||||
virtual bool get_interrupt_execution() = 0;
|
||||
virtual void set_interrupt_execution(bool v) = 0;
|
||||
virtual void local_irq(short id, bool value) = 0;
|
||||
virtual ~sc_core_adapter_if() = default;
|
||||
};
|
||||
} // namespace sysc
|
||||
#endif /* _SYSC_SC_CORE_ADAPTER_IF_H_ */
|
|
@ -0,0 +1,537 @@
|
|||
|
||||
|
||||
x86::Mem get_reg_ptr(jit_holder& jh, unsigned idx) {
|
||||
|
||||
x86::Gp tmp_ptr = jh.cc.newUIntPtr("tmp_ptr");
|
||||
jh.cc.mov(tmp_ptr, jh.regs_base_ptr);
|
||||
jh.cc.add(tmp_ptr, traits::reg_byte_offsets[idx]);
|
||||
switch(traits::reg_bit_widths[idx]) {
|
||||
case 8:
|
||||
return x86::ptr_8(tmp_ptr);
|
||||
case 16:
|
||||
return x86::ptr_16(tmp_ptr);
|
||||
case 32:
|
||||
return x86::ptr_32(tmp_ptr);
|
||||
case 64:
|
||||
return x86::ptr_64(tmp_ptr);
|
||||
default:
|
||||
throw std::runtime_error("Invalid reg size in get_reg_ptr");
|
||||
}
|
||||
}
|
||||
x86::Gp get_reg_for(jit_holder& jh, unsigned idx) {
|
||||
// TODO can check for regs in jh and return them instead of creating new ones
|
||||
switch(traits::reg_bit_widths[idx]) {
|
||||
case 8:
|
||||
return jh.cc.newInt8();
|
||||
case 16:
|
||||
return jh.cc.newInt16();
|
||||
case 32:
|
||||
return jh.cc.newInt32();
|
||||
case 64:
|
||||
return jh.cc.newInt64();
|
||||
default:
|
||||
throw std::runtime_error("Invalid reg size in get_reg_ptr");
|
||||
}
|
||||
}
|
||||
x86::Gp get_reg_for(jit_holder& jh, unsigned size, bool is_signed) {
|
||||
if(is_signed)
|
||||
switch(size) {
|
||||
case 8:
|
||||
return jh.cc.newInt8();
|
||||
case 16:
|
||||
return jh.cc.newInt16();
|
||||
case 32:
|
||||
return jh.cc.newInt32();
|
||||
case 64:
|
||||
return jh.cc.newInt64();
|
||||
default:
|
||||
throw std::runtime_error("Invalid reg size in get_reg_ptr");
|
||||
}
|
||||
else
|
||||
switch(size) {
|
||||
case 8:
|
||||
return jh.cc.newUInt8();
|
||||
case 16:
|
||||
return jh.cc.newUInt16();
|
||||
case 32:
|
||||
return jh.cc.newUInt32();
|
||||
case 64:
|
||||
return jh.cc.newUInt64();
|
||||
default:
|
||||
throw std::runtime_error("Invalid reg size in get_reg_ptr");
|
||||
}
|
||||
}
|
||||
inline x86::Gp load_reg_from_mem(jit_holder& jh, unsigned idx) {
|
||||
auto ptr = get_reg_ptr(jh, idx);
|
||||
auto reg = get_reg_for(jh, idx);
|
||||
jh.cc.mov(reg, ptr);
|
||||
return reg;
|
||||
}
|
||||
inline void write_reg_to_mem(jit_holder& jh, x86::Gp reg, unsigned idx) {
|
||||
auto ptr = get_reg_ptr(jh, idx);
|
||||
jh.cc.mov(ptr, reg);
|
||||
}
|
||||
|
||||
void gen_instr_prologue(jit_holder& jh, addr_t pc) {
|
||||
auto& cc = jh.cc;
|
||||
|
||||
cc.comment("\n//(*icount)++;");
|
||||
cc.inc(get_reg_ptr(jh, traits::ICOUNT));
|
||||
|
||||
cc.comment("\n//*pc=*next_pc;");
|
||||
cc.mov(get_reg_ptr(jh, traits::PC), jh.next_pc);
|
||||
|
||||
cc.comment("\n//*trap_state=*pending_trap;");
|
||||
x86::Gp current_trap_state = get_reg_for(jh, traits::TRAP_STATE);
|
||||
cc.mov(current_trap_state, get_reg_ptr(jh, traits::TRAP_STATE));
|
||||
cc.mov(get_reg_ptr(jh, traits::PENDING_TRAP), current_trap_state);
|
||||
|
||||
cc.comment("\n//increment *next_pc");
|
||||
cc.mov(jh.next_pc, pc);
|
||||
}
|
||||
void gen_instr_epilogue(jit_holder& jh) {
|
||||
auto& cc = jh.cc;
|
||||
|
||||
cc.comment("\n//if(*trap_state!=0) goto trap_entry;");
|
||||
x86::Gp current_trap_state = get_reg_for(jh, traits::TRAP_STATE);
|
||||
cc.mov(current_trap_state, get_reg_ptr(jh, traits::TRAP_STATE));
|
||||
cc.cmp(current_trap_state, 0);
|
||||
cc.jne(jh.trap_entry);
|
||||
|
||||
// TODO: Does not need to be done for every instruction, only when needed
|
||||
cc.comment("\n//write back regs to mem");
|
||||
write_reg_to_mem(jh, jh.pc, traits::PC);
|
||||
write_reg_to_mem(jh, jh.next_pc, traits::NEXT_PC);
|
||||
}
|
||||
void gen_block_prologue(jit_holder& jh) override {
|
||||
|
||||
jh.pc = load_reg_from_mem(jh, traits::PC);
|
||||
jh.next_pc = load_reg_from_mem(jh, traits::NEXT_PC);
|
||||
}
|
||||
void gen_block_epilogue(jit_holder& jh) override {
|
||||
x86::Compiler& cc = jh.cc;
|
||||
cc.comment("\n//return *next_pc;");
|
||||
cc.ret(jh.next_pc);
|
||||
|
||||
cc.bind(jh.trap_entry);
|
||||
cc.comment("\n//Prepare for enter_trap;");
|
||||
// Make sure cached values are written back
|
||||
cc.comment("\n//write back regs to mem");
|
||||
write_reg_to_mem(jh, jh.pc, traits::PC);
|
||||
write_reg_to_mem(jh, jh.next_pc, traits::NEXT_PC);
|
||||
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_reg_ptr(jh, traits::TRAP_STATE));
|
||||
|
||||
x86::Gp current_pc = get_reg_for(jh, traits::PC);
|
||||
cc.mov(current_pc, get_reg_ptr(jh, traits::PC));
|
||||
|
||||
x86::Gp instr = cc.newInt32("instr");
|
||||
cc.mov(instr, 0); // this is not correct
|
||||
cc.comment("\n//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_reg_ptr(jh, traits::NEXT_PC));
|
||||
cc.mov(jh.next_pc, current_next_pc);
|
||||
|
||||
cc.comment("\n//*last_branch = std::numeric_limits<uint32_t>::max();");
|
||||
cc.mov(get_reg_ptr(jh, traits::LAST_BRANCH), std::numeric_limits<uint32_t>::max());
|
||||
cc.comment("\n//return *next_pc;");
|
||||
cc.ret(jh.next_pc);
|
||||
}
|
||||
/*
|
||||
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<uint32_t>(traits::NEXT_PC) = std::numeric_limits<uint32_t>::max();
|
||||
}
|
||||
*/
|
||||
inline void 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_reg_ptr(jh, traits::TRAP_STATE), tmp1);
|
||||
auto tmp2 = get_reg_for(jh, traits::NEXT_PC);
|
||||
cc.mov(tmp2, std::numeric_limits<uint32_t>::max());
|
||||
cc.mov(get_reg_ptr(jh, traits::NEXT_PC), tmp2);
|
||||
}
|
||||
inline void gen_wait(jit_holder& jh, unsigned type) { jh.cc.comment("//gen_wait"); }
|
||||
inline void gen_leave(jit_holder& jh, unsigned lvl) { jh.cc.comment("//gen_leave"); }
|
||||
|
||||
enum operation { add, sub, band, bor, bxor, shl, sar, shr };
|
||||
|
||||
template <typename T, typename = std::enable_if_t<std::is_integral<T>::value || std::is_same<T, x86::Gp>::value>>
|
||||
x86::Gp gen_operation(jit_holder& jh, operation op, x86::Gp a, T b) {
|
||||
x86::Compiler& cc = jh.cc;
|
||||
switch(op) {
|
||||
case add: {
|
||||
cc.add(a, b);
|
||||
break;
|
||||
}
|
||||
case sub: {
|
||||
cc.sub(a, b);
|
||||
break;
|
||||
}
|
||||
case band: {
|
||||
cc.and_(a, b);
|
||||
break;
|
||||
}
|
||||
case bor: {
|
||||
cc.or_(a, b);
|
||||
break;
|
||||
}
|
||||
case bxor: {
|
||||
cc.xor_(a, b);
|
||||
break;
|
||||
}
|
||||
case shl: {
|
||||
cc.shl(a, b);
|
||||
break;
|
||||
}
|
||||
case sar: {
|
||||
cc.sar(a, b);
|
||||
break;
|
||||
}
|
||||
case shr: {
|
||||
cc.shr(a, b);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw std::runtime_error(fmt::format("Current operation {} not supported in gen_operation (operation)", op));
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
enum three_operand_operation { imul, mul, idiv, div, srem, urem };
|
||||
|
||||
x86::Gp gen_operation(jit_holder& jh, three_operand_operation op, x86::Gp a, x86::Gp b) {
|
||||
x86::Compiler& cc = jh.cc;
|
||||
switch(op) {
|
||||
case imul: {
|
||||
x86::Gp dummy = cc.newInt64();
|
||||
cc.imul(dummy, a.r64(), b.r64());
|
||||
return a;
|
||||
}
|
||||
case mul: {
|
||||
x86::Gp dummy = cc.newInt64();
|
||||
cc.mul(dummy, a.r64(), b.r64());
|
||||
return a;
|
||||
}
|
||||
case idiv: {
|
||||
x86::Gp dummy = cc.newInt64();
|
||||
cc.mov(dummy, 0);
|
||||
cc.idiv(dummy, a.r64(), b.r64());
|
||||
return a;
|
||||
}
|
||||
case div: {
|
||||
x86::Gp dummy = cc.newInt64();
|
||||
cc.mov(dummy, 0);
|
||||
cc.div(dummy, a.r64(), b.r64());
|
||||
return a;
|
||||
}
|
||||
case srem: {
|
||||
x86::Gp rem = cc.newInt32();
|
||||
cc.mov(rem, 0);
|
||||
auto a_reg = cc.newInt32();
|
||||
cc.mov(a_reg, a.r32());
|
||||
cc.idiv(rem, a_reg, b.r32());
|
||||
return rem;
|
||||
}
|
||||
case urem: {
|
||||
x86::Gp rem = cc.newInt32();
|
||||
cc.mov(rem, 0);
|
||||
auto a_reg = cc.newInt32();
|
||||
cc.mov(a_reg, a.r32());
|
||||
cc.div(rem, a_reg, b.r32());
|
||||
return rem;
|
||||
}
|
||||
|
||||
default:
|
||||
throw std::runtime_error(fmt::format("Current operation {} not supported in gen_operation (three_operand)", op));
|
||||
}
|
||||
return a;
|
||||
}
|
||||
template <typename T, typename = std::enable_if_t<std::is_integral<T>::value>>
|
||||
x86::Gp gen_operation(jit_holder& jh, three_operand_operation op, x86::Gp a, T b) {
|
||||
x86::Gp b_reg = jh.cc.newInt32();
|
||||
/* switch(a.size()){
|
||||
case 1: b_reg = jh.cc.newInt8(); break;
|
||||
case 2: b_reg = jh.cc.newInt16(); break;
|
||||
case 4: b_reg = jh.cc.newInt32(); break;
|
||||
case 8: b_reg = jh.cc.newInt64(); break;
|
||||
default: throw std::runtime_error(fmt::format("Invalid size ({}) in gen operation", a.size()));
|
||||
} */
|
||||
jh.cc.mov(b_reg, b);
|
||||
return gen_operation(jh, op, a, b_reg);
|
||||
}
|
||||
enum comparison_operation { land, lor, eq, ne, lt, ltu, gt, gtu, lte, lteu, gte, gteu };
|
||||
|
||||
template <typename T, typename = std::enable_if_t<std::is_integral<T>::value || std::is_same<T, x86::Gp>::value>>
|
||||
x86::Gp gen_operation(jit_holder& jh, comparison_operation op, x86::Gp a, T b) {
|
||||
x86::Compiler& cc = jh.cc;
|
||||
x86::Gp tmp = cc.newInt8();
|
||||
cc.mov(tmp, 1);
|
||||
Label label_then = cc.newLabel();
|
||||
cc.cmp(a, b);
|
||||
switch(op) {
|
||||
case eq:
|
||||
cc.je(label_then);
|
||||
break;
|
||||
case ne:
|
||||
cc.jne(label_then);
|
||||
break;
|
||||
case lt:
|
||||
cc.jl(label_then);
|
||||
break;
|
||||
case ltu:
|
||||
cc.jb(label_then);
|
||||
break;
|
||||
case gt:
|
||||
cc.jg(label_then);
|
||||
break;
|
||||
case gtu:
|
||||
cc.ja(label_then);
|
||||
break;
|
||||
case lte:
|
||||
cc.jle(label_then);
|
||||
break;
|
||||
case lteu:
|
||||
cc.jbe(label_then);
|
||||
break;
|
||||
case gte:
|
||||
cc.jge(label_then);
|
||||
break;
|
||||
case gteu:
|
||||
cc.jae(label_then);
|
||||
break;
|
||||
case land: {
|
||||
Label label_false = cc.newLabel();
|
||||
cc.cmp(a, 0);
|
||||
cc.je(label_false);
|
||||
auto b_reg = cc.newInt8();
|
||||
cc.mov(b_reg, b);
|
||||
cc.cmp(b_reg, 0);
|
||||
cc.je(label_false);
|
||||
cc.jmp(label_then);
|
||||
cc.bind(label_false);
|
||||
break;
|
||||
}
|
||||
case lor: {
|
||||
cc.cmp(a, 0);
|
||||
cc.jne(label_then);
|
||||
auto b_reg = cc.newInt8();
|
||||
cc.mov(b_reg, b);
|
||||
cc.cmp(b_reg, 0);
|
||||
cc.jne(label_then);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw std::runtime_error(fmt::format("Current operation {} not supported in gen_operation (comparison)", op));
|
||||
}
|
||||
cc.mov(tmp, 0);
|
||||
cc.bind(label_then);
|
||||
return tmp;
|
||||
}
|
||||
enum binary_operation { lnot, inc, dec, bnot, neg };
|
||||
|
||||
x86::Gp gen_operation(jit_holder& jh, binary_operation op, x86::Gp a) {
|
||||
x86::Compiler& cc = jh.cc;
|
||||
switch(op) {
|
||||
case lnot:
|
||||
throw std::runtime_error("Current operation not supported in gen_operation(lnot)");
|
||||
case inc: {
|
||||
cc.inc(a);
|
||||
break;
|
||||
}
|
||||
case dec: {
|
||||
cc.dec(a);
|
||||
break;
|
||||
}
|
||||
case bnot: {
|
||||
cc.not_(a);
|
||||
break;
|
||||
}
|
||||
case neg: {
|
||||
cc.neg(a);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw std::runtime_error(fmt::format("Current operation {} not supported in gen_operation (unary)", op));
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
template <typename T, typename = std::enable_if_t<std::is_integral<T>::value>>
|
||||
inline x86::Gp gen_ext(jit_holder& jh, T val, unsigned size, bool is_signed) {
|
||||
auto val_reg = get_reg_for(jh, sizeof(val) * 8, is_signed);
|
||||
jh.cc.mov(val_reg, val);
|
||||
return gen_ext(jh, val_reg, size, is_signed);
|
||||
}
|
||||
inline x86::Gp gen_ext(jit_holder& jh, x86::Gp val, unsigned size, bool is_signed) {
|
||||
auto& cc = jh.cc;
|
||||
if(is_signed) {
|
||||
switch(val.size()) {
|
||||
case 1:
|
||||
cc.cbw(val);
|
||||
break;
|
||||
case 2:
|
||||
cc.cwde(val);
|
||||
break;
|
||||
case 4:
|
||||
cc.cdqe(val);
|
||||
break;
|
||||
case 8:
|
||||
break;
|
||||
default:
|
||||
throw std::runtime_error("Invalid register size in gen_ext");
|
||||
}
|
||||
}
|
||||
switch(size) {
|
||||
case 8:
|
||||
cc.and_(val, std::numeric_limits<uint8_t>::max());
|
||||
return val.r8();
|
||||
case 16:
|
||||
cc.and_(val, std::numeric_limits<uint16_t>::max());
|
||||
return val.r16();
|
||||
case 32:
|
||||
cc.and_(val, std::numeric_limits<uint32_t>::max());
|
||||
return val.r32();
|
||||
case 64:
|
||||
cc.and_(val, std::numeric_limits<uint64_t>::max());
|
||||
return val.r64();
|
||||
case 128:
|
||||
return val.r64();
|
||||
default:
|
||||
throw std::runtime_error("Invalid size in gen_ext");
|
||||
}
|
||||
}
|
||||
inline x86::Gp gen_read_mem(jit_holder& jh, mem_type_e type, x86::Gp addr, uint32_t length) {
|
||||
x86::Compiler& cc = jh.cc;
|
||||
auto ret_reg = cc.newInt32();
|
||||
|
||||
auto mem_type_reg = cc.newInt32();
|
||||
cc.mov(mem_type_reg, type);
|
||||
|
||||
auto space_reg = cc.newInt32();
|
||||
cc.mov(space_reg, static_cast<uint16_t>(iss::address_type::VIRTUAL));
|
||||
|
||||
auto val_ptr = cc.newUIntPtr();
|
||||
cc.mov(val_ptr, read_mem_buf);
|
||||
|
||||
InvokeNode* invokeNode;
|
||||
uint64_t mask = 0;
|
||||
x86::Gp val_reg = cc.newInt64();
|
||||
|
||||
switch(length) {
|
||||
case 1: {
|
||||
cc.invoke(&invokeNode, &read_mem1, FuncSignatureT<uint32_t, uint64_t, uint32_t, uint32_t, uint64_t, uintptr_t>());
|
||||
mask = std::numeric_limits<uint8_t>::max();
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
cc.invoke(&invokeNode, &read_mem2, FuncSignatureT<uint32_t, uint64_t, uint32_t, uint32_t, uint64_t, uintptr_t>());
|
||||
mask = std::numeric_limits<uint16_t>::max();
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
cc.invoke(&invokeNode, &read_mem4, FuncSignatureT<uint32_t, uint64_t, uint32_t, uint32_t, uint64_t, uintptr_t>());
|
||||
mask = std::numeric_limits<uint32_t>::max();
|
||||
break;
|
||||
}
|
||||
case 8: {
|
||||
cc.invoke(&invokeNode, &read_mem8, FuncSignatureT<uint32_t, uint64_t, uint32_t, uint32_t, uint64_t, uintptr_t>());
|
||||
mask = std::numeric_limits<uint64_t>::max();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw std::runtime_error(fmt::format("Invalid length ({}) in gen_read_mem", length));
|
||||
}
|
||||
|
||||
invokeNode->setRet(0, ret_reg);
|
||||
invokeNode->setArg(0, jh.arch_if_ptr);
|
||||
invokeNode->setArg(1, space_reg);
|
||||
invokeNode->setArg(2, mem_type_reg);
|
||||
invokeNode->setArg(3, addr);
|
||||
invokeNode->setArg(4, val_ptr);
|
||||
cc.cmp(ret_reg, 0);
|
||||
cc.jne(jh.trap_entry);
|
||||
|
||||
cc.mov(val_reg, x86::ptr_64(val_ptr));
|
||||
cc.and_(val_reg, mask);
|
||||
return val_reg;
|
||||
}
|
||||
inline x86::Gp gen_read_mem(jit_holder& jh, mem_type_e type, x86::Gp addr, x86::Gp length) {
|
||||
throw std::runtime_error("Invalid gen_read_mem");
|
||||
}
|
||||
inline x86::Gp gen_read_mem(jit_holder& jh, mem_type_e type, uint64_t addr, x86::Gp length) {
|
||||
throw std::runtime_error("Invalid gen_read_mem");
|
||||
}
|
||||
inline x86::Gp gen_read_mem(jit_holder& jh, mem_type_e type, uint64_t addr, uint32_t length) {
|
||||
auto addr_reg = jh.cc.newInt64();
|
||||
jh.cc.mov(addr_reg, addr);
|
||||
|
||||
return gen_read_mem(jh, type, addr_reg, length);
|
||||
}
|
||||
inline void gen_write_mem(jit_holder& jh, mem_type_e type, x86::Gp addr, int64_t val, uint32_t length) {
|
||||
auto val_reg = get_reg_for(jh, length * 8, true);
|
||||
jh.cc.mov(val_reg, val);
|
||||
gen_write_mem(jh, type, addr, val_reg, length);
|
||||
}
|
||||
inline void gen_write_mem(jit_holder& jh, mem_type_e type, x86::Gp addr, x86::Gp val, uint32_t length) {
|
||||
x86::Compiler& cc = jh.cc;
|
||||
assert(val.size() == length);
|
||||
auto mem_type_reg = cc.newInt32();
|
||||
jh.cc.mov(mem_type_reg, type);
|
||||
auto space_reg = cc.newInt32();
|
||||
jh.cc.mov(space_reg, static_cast<uint16_t>(iss::address_type::VIRTUAL));
|
||||
auto ret_reg = cc.newInt32();
|
||||
InvokeNode* invokeNode;
|
||||
switch(length) {
|
||||
case 1:
|
||||
cc.invoke(&invokeNode, &write_mem1, FuncSignatureT<uint32_t, uint64_t, uint32_t, uint32_t, uint64_t, uint8_t>());
|
||||
|
||||
break;
|
||||
case 2:
|
||||
cc.invoke(&invokeNode, &write_mem2, FuncSignatureT<uint32_t, uint64_t, uint32_t, uint32_t, uint64_t, uint16_t>());
|
||||
break;
|
||||
case 4:
|
||||
cc.invoke(&invokeNode, &write_mem4, FuncSignatureT<uint32_t, uint64_t, uint32_t, uint32_t, uint64_t, uint32_t>());
|
||||
break;
|
||||
case 8:
|
||||
cc.invoke(&invokeNode, &write_mem8, FuncSignatureT<uint32_t, uint64_t, uint32_t, uint32_t, uint64_t, uint64_t>());
|
||||
|
||||
break;
|
||||
default:
|
||||
throw std::runtime_error("Invalid register size in gen_ext");
|
||||
}
|
||||
invokeNode->setRet(0, ret_reg);
|
||||
invokeNode->setArg(0, jh.arch_if_ptr);
|
||||
invokeNode->setArg(1, space_reg);
|
||||
invokeNode->setArg(2, mem_type_reg);
|
||||
invokeNode->setArg(3, addr);
|
||||
invokeNode->setArg(4, val);
|
||||
|
||||
cc.cmp(ret_reg, 0);
|
||||
cc.jne(jh.trap_entry);
|
||||
}
|
||||
inline void gen_write_mem(jit_holder& jh, mem_type_e type, uint64_t addr, x86::Gp val, uint32_t length) {
|
||||
auto addr_reg = jh.cc.newUInt64();
|
||||
jh.cc.mov(addr_reg, addr);
|
||||
gen_write_mem(jh, type, addr_reg, val, length);
|
||||
}
|
||||
inline void gen_write_mem(jit_holder& jh, mem_type_e type, uint64_t addr, int64_t val, uint32_t length) {
|
||||
auto val_reg = get_reg_for(jh, length * 8, true);
|
||||
jh.cc.mov(val_reg, val);
|
||||
|
||||
auto addr_reg = jh.cc.newUInt64();
|
||||
jh.cc.mov(addr_reg, addr);
|
||||
gen_write_mem(jh, type, addr_reg, val_reg, length);
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -35,32 +35,24 @@
|
|||
#include "fp_functions.h"
|
||||
|
||||
extern "C" {
|
||||
#include <softfloat.h>
|
||||
#include "internals.h"
|
||||
#include "specialize.h"
|
||||
#include <softfloat.h>
|
||||
}
|
||||
|
||||
#include <limits>
|
||||
|
||||
using this_t = uint8_t*;
|
||||
const uint8_t rmm_map[] = {
|
||||
softfloat_round_near_even /*RNE*/,
|
||||
softfloat_round_minMag/*RTZ*/,
|
||||
softfloat_round_min/*RDN*/,
|
||||
softfloat_round_max/*RUP?*/,
|
||||
softfloat_round_near_maxMag /*RMM*/,
|
||||
softfloat_round_max/*RTZ*/,
|
||||
softfloat_round_max/*RTZ*/,
|
||||
softfloat_round_max/*RTZ*/,
|
||||
softfloat_round_near_even /*RNE*/, softfloat_round_minMag /*RTZ*/, softfloat_round_min /*RDN*/, softfloat_round_max /*RUP?*/,
|
||||
softfloat_round_near_maxMag /*RMM*/, softfloat_round_max /*RTZ*/, softfloat_round_max /*RTZ*/, softfloat_round_max /*RTZ*/,
|
||||
};
|
||||
|
||||
const uint32_t quiet_nan32 = 0x7fC00000;
|
||||
|
||||
extern "C" {
|
||||
|
||||
uint32_t fget_flags(){
|
||||
return softfloat_exceptionFlags&0x1f;
|
||||
}
|
||||
uint32_t fget_flags() { return softfloat_exceptionFlags & 0x1f; }
|
||||
|
||||
uint32_t fadd_s(uint32_t v1, uint32_t v2, uint8_t mode) {
|
||||
float32_t v1f{v1}, v2f{v2};
|
||||
|
@ -110,7 +102,8 @@ uint32_t fcmp_s(uint32_t v1, uint32_t v2, uint32_t op) {
|
|||
switch(op) {
|
||||
case 0:
|
||||
if(nan | snan) {
|
||||
if(snan) softfloat_raiseFlags(softfloat_flag_invalid);
|
||||
if(snan)
|
||||
softfloat_raiseFlags(softfloat_flag_invalid);
|
||||
return 0;
|
||||
} else
|
||||
return f32_eq(v1f, v2f) ? 1 : 0;
|
||||
|
@ -160,7 +153,8 @@ uint32_t fmadd_s(uint32_t v1, uint32_t v2, uint32_t v3, uint32_t op, uint8_t mod
|
|||
softfloat_roundingMode = rmm_map[mode & 0x7];
|
||||
softfloat_exceptionFlags = 0;
|
||||
float32_t res = softfloat_mulAddF32(v1, v2, v3, op & 0x1);
|
||||
if(op>1) res.v ^= 1ULL<<31;
|
||||
if(op > 1)
|
||||
res.v ^= 1ULL << 31;
|
||||
return res.v;
|
||||
}
|
||||
|
||||
|
@ -170,11 +164,11 @@ uint32_t fsel_s(uint32_t v1, uint32_t v2, uint32_t op) {
|
|||
bool v2_nan = (v2 & defaultNaNF32UI) == defaultNaNF32UI;
|
||||
bool v1_snan = softfloat_isSigNaNF32UI(v1);
|
||||
bool v2_snan = softfloat_isSigNaNF32UI(v2);
|
||||
if (v1_snan || v2_snan) softfloat_raiseFlags(softfloat_flag_invalid);
|
||||
if(v1_snan || v2_snan)
|
||||
softfloat_raiseFlags(softfloat_flag_invalid);
|
||||
if(v1_nan || v1_snan)
|
||||
return (v2_nan || v2_snan) ? defaultNaNF32UI : v2;
|
||||
else
|
||||
if (v2_nan || v2_snan)
|
||||
else if(v2_nan || v2_snan)
|
||||
return v1;
|
||||
else {
|
||||
if((v1 & 0x7fffffff) == 0 && (v2 & 0x7fffffff) == 0) {
|
||||
|
@ -202,17 +196,10 @@ uint32_t fclass_s( uint32_t v1 ){
|
|||
bool isNaN = isNaNF32UI(uiA);
|
||||
bool isSNaN = softfloat_isSigNaNF32UI(uiA);
|
||||
|
||||
return
|
||||
( sign && infOrNaN && fracZero ) << 0 |
|
||||
( sign && !infOrNaN && !subnormalOrZero ) << 1 |
|
||||
( sign && subnormalOrZero && !fracZero ) << 2 |
|
||||
( sign && subnormalOrZero && fracZero ) << 3 |
|
||||
( !sign && infOrNaN && fracZero ) << 7 |
|
||||
( !sign && !infOrNaN && !subnormalOrZero ) << 6 |
|
||||
( !sign && subnormalOrZero && !fracZero ) << 5 |
|
||||
( !sign && subnormalOrZero && fracZero ) << 4 |
|
||||
( isNaN && isSNaN ) << 8 |
|
||||
( isNaN && !isSNaN ) << 9;
|
||||
return (sign && infOrNaN && fracZero) << 0 | (sign && !infOrNaN && !subnormalOrZero) << 1 |
|
||||
(sign && subnormalOrZero && !fracZero) << 2 | (sign && subnormalOrZero && fracZero) << 3 | (!sign && infOrNaN && fracZero) << 7 |
|
||||
(!sign && !infOrNaN && !subnormalOrZero) << 6 | (!sign && subnormalOrZero && !fracZero) << 5 |
|
||||
(!sign && subnormalOrZero && fracZero) << 4 | (isNaN && isSNaN) << 8 | (isNaN && !isSNaN) << 9;
|
||||
}
|
||||
|
||||
uint32_t fconv_d2f(uint64_t v1, uint8_t mode) {
|
||||
|
@ -287,7 +274,8 @@ uint64_t fcmp_d(uint64_t v1, uint64_t v2, uint32_t op) {
|
|||
switch(op) {
|
||||
case 0:
|
||||
if(nan | snan) {
|
||||
if(snan) softfloat_raiseFlags(softfloat_flag_invalid);
|
||||
if(snan)
|
||||
softfloat_raiseFlags(softfloat_flag_invalid);
|
||||
return 0;
|
||||
} else
|
||||
return f64_eq(v1f, v2f) ? 1 : 0;
|
||||
|
@ -337,7 +325,8 @@ uint64_t fmadd_d(uint64_t v1, uint64_t v2, uint64_t v3, uint32_t op, uint8_t mod
|
|||
softfloat_roundingMode = rmm_map[mode & 0x7];
|
||||
softfloat_exceptionFlags = 0;
|
||||
float64_t res = softfloat_mulAddF64(v1, v2, v3, op & 0x1);
|
||||
if(op>1) res.v ^= 1ULL<<63;
|
||||
if(op > 1)
|
||||
res.v ^= 1ULL << 63;
|
||||
return res.v;
|
||||
}
|
||||
|
||||
|
@ -347,22 +336,19 @@ uint64_t fsel_d(uint64_t v1, uint64_t v2, uint32_t op) {
|
|||
bool v2_nan = (v2 & defaultNaNF64UI) == defaultNaNF64UI;
|
||||
bool v1_snan = softfloat_isSigNaNF64UI(v1);
|
||||
bool v2_snan = softfloat_isSigNaNF64UI(v2);
|
||||
if (v1_snan || v2_snan) softfloat_raiseFlags(softfloat_flag_invalid);
|
||||
if(v1_snan || v2_snan)
|
||||
softfloat_raiseFlags(softfloat_flag_invalid);
|
||||
if(v1_nan || v1_snan)
|
||||
return (v2_nan || v2_snan) ? defaultNaNF64UI : v2;
|
||||
else
|
||||
if (v2_nan || v2_snan)
|
||||
else if(v2_nan || v2_snan)
|
||||
return v1;
|
||||
else {
|
||||
if((v1 & std::numeric_limits<int64_t>::max()) == 0 && (v2 & std::numeric_limits<int64_t>::max()) == 0) {
|
||||
return op == 0 ?
|
||||
((v1 & std::numeric_limits<int64_t>::min()) ? v1 : v2) :
|
||||
((v1 & std::numeric_limits<int64_t>::min()) ? v2 : v1);
|
||||
return op == 0 ? ((v1 & std::numeric_limits<int64_t>::min()) ? v1 : v2)
|
||||
: ((v1 & std::numeric_limits<int64_t>::min()) ? v2 : v1);
|
||||
} else {
|
||||
float64_t v1f{v1}, v2f{v2};
|
||||
return op == 0 ?
|
||||
(f64_lt(v1f, v2f) ? v1 : v2) :
|
||||
(f64_lt(v1f, v2f) ? v2 : v1);
|
||||
return op == 0 ? (f64_lt(v1f, v2f) ? v1 : v2) : (f64_lt(v1f, v2f) ? v2 : v1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -383,17 +369,10 @@ uint64_t fclass_d(uint64_t v1 ){
|
|||
bool isNaN = isNaNF64UI(uiA);
|
||||
bool isSNaN = softfloat_isSigNaNF64UI(uiA);
|
||||
|
||||
return
|
||||
( sign && infOrNaN && fracZero ) << 0 |
|
||||
( sign && !infOrNaN && !subnormalOrZero ) << 1 |
|
||||
( sign && subnormalOrZero && !fracZero ) << 2 |
|
||||
( sign && subnormalOrZero && fracZero ) << 3 |
|
||||
( !sign && infOrNaN && fracZero ) << 7 |
|
||||
( !sign && !infOrNaN && !subnormalOrZero ) << 6 |
|
||||
( !sign && subnormalOrZero && !fracZero ) << 5 |
|
||||
( !sign && subnormalOrZero && fracZero ) << 4 |
|
||||
( isNaN && isSNaN ) << 8 |
|
||||
( isNaN && !isSNaN ) << 9;
|
||||
return (sign && infOrNaN && fracZero) << 0 | (sign && !infOrNaN && !subnormalOrZero) << 1 |
|
||||
(sign && subnormalOrZero && !fracZero) << 2 | (sign && subnormalOrZero && fracZero) << 3 | (!sign && infOrNaN && fracZero) << 7 |
|
||||
(!sign && !infOrNaN && !subnormalOrZero) << 6 | (!sign && subnormalOrZero && !fracZero) << 5 |
|
||||
(!sign && subnormalOrZero && fracZero) << 4 | (isNaN && isSNaN) << 8 | (isNaN && !isSNaN) << 9;
|
||||
}
|
||||
|
||||
uint64_t fcvt_32_64(uint32_t v1, uint32_t op, uint8_t mode) {
|
||||
|
@ -445,4 +424,3 @@ uint32_t unbox_s(uint64_t v){
|
|||
return v & std::numeric_limits<uint32_t>::max();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
/vm_tgc_*.cpp
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -36,9 +36,9 @@
|
|||
#include <iss/llvm/vm_base.h>
|
||||
|
||||
extern "C" {
|
||||
#include <softfloat.h>
|
||||
#include "internals.h"
|
||||
#include "specialize.h"
|
||||
#include <softfloat.h>
|
||||
}
|
||||
|
||||
#include <limits>
|
||||
|
@ -69,7 +69,6 @@ using namespace ::llvm;
|
|||
FunctionType* NAME##_type = FunctionType::get(RET, NAME##_args, false); \
|
||||
mod->getOrInsertFunction(#NAME, NAME##_type);
|
||||
|
||||
|
||||
void add_fp_functions_2_module(Module* mod, uint32_t flen, uint32_t xlen) {
|
||||
if(flen) {
|
||||
FDECL(fget_flags, INT_TYPE(32));
|
||||
|
@ -99,11 +98,10 @@ void add_fp_functions_2_module(Module *mod, uint32_t flen, uint32_t xlen) {
|
|||
FDECL(fsel_d, INT_TYPE(64), INT_TYPE(64), INT_TYPE(64), INT_TYPE(32));
|
||||
FDECL(fclass_d, INT_TYPE(64), INT_TYPE(64));
|
||||
FDECL(unbox_s, INT_TYPE(32), INT_TYPE(64));
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace fp_impl
|
||||
} // namespace llvm
|
||||
} // namespace iss
|
||||
|
|
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
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
Loading…
Reference in New Issue