Compare commits
71 Commits
feature/is
...
e48597b2b7
| Author | SHA1 | Date | |
|---|---|---|---|
| e48597b2b7 | |||
| 458c773e19 | |||
| b3f40f9b15 | |||
| 6419ad471e | |||
| 759061b569 | |||
| 2115e9ceae | |||
| 2bea95c1a7 | |||
| 7001b693ae | |||
| e6f11081eb | |||
| 09db0cd35d | |||
| 980c8031c3 | |||
| b86d7a517d | |||
| b7478965ab | |||
| bf4a6deb86 | |||
| ffe730219d | |||
| 60c926c921 | |||
| 9371a09b71 | |||
| 4c3a7386b0 | |||
| 82c26acfc8 | |||
| 3a86f4f9de | |||
| 74ff1d455a | |||
| aa12e93177 | |||
| ae4322c1b9 | |||
| 9180ad1f9c | |||
| ee6a068b06 | |||
| b9b165465d | |||
| b97853ff5a | |||
| b7f023756e | |||
| 2095ac985b | |||
| 3fb8fe765a | |||
| 5fd226b670 | |||
| 417076f8e6 | |||
| 70839bbbf2 | |||
| 8db0cc5d05 | |||
| 212fb1c8ff | |||
| f74f98f361 | |||
| f074092a78 | |||
| 633c0d21a0 | |||
| 51f6fbe0dd | |||
| de45d06878 | |||
| c7038cafa5 | |||
| 40f50b0ec0 | |||
| b360fc2c75 | |||
| e21f8dc379 | |||
| 8ee3ac90f7 | |||
| d5763d2f36 | |||
| b5d915f389 | |||
| 813b40409d | |||
| c8a4a4c736 | |||
| 18e08cfc50 | |||
| 20e920338c | |||
| e151416f58 | |||
| 24de2bbdf5 | |||
| e68f9c573f | |||
| f38cc7d8b9 | |||
| 7af7e040da | |||
| 6e52af168b | |||
| bd0d15f3a2 | |||
| c78026b720 | |||
| edba497fa1 | |||
| 94e46b9968 | |||
| 9459632f6c | |||
| a0ca3cdfa5 | |||
| 720236ec3f | |||
| 957145ca84 | |||
| 0b719a4b57 | |||
| 57da07eb17 | |||
| b4b03f7850 | |||
| 145a0cf68b | |||
| 1cef7de8c7 | |||
| e95f422aab |
@@ -1,4 +1,3 @@
|
|||||||
---
|
|
||||||
Language: Cpp
|
Language: Cpp
|
||||||
# BasedOnStyle: LLVM
|
# BasedOnStyle: LLVM
|
||||||
# should be in line with IndentWidth
|
# should be in line with IndentWidth
|
||||||
@@ -13,8 +12,8 @@ AllowAllParametersOfDeclarationOnNextLine: true
|
|||||||
AllowShortBlocksOnASingleLine: false
|
AllowShortBlocksOnASingleLine: false
|
||||||
AllowShortCaseLabelsOnASingleLine: false
|
AllowShortCaseLabelsOnASingleLine: false
|
||||||
AllowShortFunctionsOnASingleLine: All
|
AllowShortFunctionsOnASingleLine: All
|
||||||
AllowShortIfStatementsOnASingleLine: true
|
AllowShortIfStatementsOnASingleLine: false
|
||||||
AllowShortLoopsOnASingleLine: true
|
AllowShortLoopsOnASingleLine: false
|
||||||
AlwaysBreakAfterDefinitionReturnType: None
|
AlwaysBreakAfterDefinitionReturnType: None
|
||||||
AlwaysBreakAfterReturnType: None
|
AlwaysBreakAfterReturnType: None
|
||||||
AlwaysBreakBeforeMultilineStrings: false
|
AlwaysBreakBeforeMultilineStrings: false
|
||||||
@@ -39,8 +38,8 @@ BreakBeforeTernaryOperators: true
|
|||||||
BreakConstructorInitializersBeforeComma: true
|
BreakConstructorInitializersBeforeComma: true
|
||||||
BreakAfterJavaFieldAnnotations: false
|
BreakAfterJavaFieldAnnotations: false
|
||||||
BreakStringLiterals: true
|
BreakStringLiterals: true
|
||||||
ColumnLimit: 120
|
ColumnLimit: 140
|
||||||
CommentPragmas: '^ IWYU pragma:'
|
CommentPragmas: '^( IWYU pragma:| @suppress)'
|
||||||
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
||||||
ConstructorInitializerIndentWidth: 0
|
ConstructorInitializerIndentWidth: 0
|
||||||
ContinuationIndentWidth: 4
|
ContinuationIndentWidth: 4
|
||||||
@@ -76,13 +75,13 @@ PenaltyBreakFirstLessLess: 120
|
|||||||
PenaltyBreakString: 1000
|
PenaltyBreakString: 1000
|
||||||
PenaltyExcessCharacter: 1000000
|
PenaltyExcessCharacter: 1000000
|
||||||
PenaltyReturnTypeOnItsOwnLine: 60
|
PenaltyReturnTypeOnItsOwnLine: 60
|
||||||
PointerAlignment: Right
|
PointerAlignment: Left
|
||||||
ReflowComments: true
|
ReflowComments: true
|
||||||
SortIncludes: true
|
SortIncludes: true
|
||||||
SpaceAfterCStyleCast: false
|
SpaceAfterCStyleCast: false
|
||||||
SpaceAfterTemplateKeyword: true
|
SpaceAfterTemplateKeyword: true
|
||||||
SpaceBeforeAssignmentOperators: true
|
SpaceBeforeAssignmentOperators: true
|
||||||
SpaceBeforeParens: ControlStatements
|
SpaceBeforeParens: Never
|
||||||
SpaceInEmptyParentheses: false
|
SpaceInEmptyParentheses: false
|
||||||
SpacesBeforeTrailingComments: 1
|
SpacesBeforeTrailingComments: 1
|
||||||
SpacesInAngles: false
|
SpacesInAngles: false
|
||||||
|
|||||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,5 +1,6 @@
|
|||||||
.DS_Store
|
.DS_Store
|
||||||
/*.il
|
/*.il
|
||||||
|
/.settings
|
||||||
/avr-instr.html
|
/avr-instr.html
|
||||||
/blink.S
|
/blink.S
|
||||||
/flash.*
|
/flash.*
|
||||||
@@ -14,7 +15,6 @@
|
|||||||
/*.ods
|
/*.ods
|
||||||
/build*/
|
/build*/
|
||||||
/*.logs
|
/*.logs
|
||||||
language.settings.xml
|
|
||||||
/*.gtkw
|
/*.gtkw
|
||||||
/Debug wo LLVM/
|
/Debug wo LLVM/
|
||||||
/*.txdb
|
/*.txdb
|
||||||
|
|||||||
@@ -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
|
|
||||||
174
CMakeLists.txt
174
CMakeLists.txt
@@ -1,80 +1,74 @@
|
|||||||
cmake_minimum_required(VERSION 3.12)
|
cmake_minimum_required(VERSION 3.12)
|
||||||
|
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
|
||||||
###############################################################################
|
###############################################################################
|
||||||
#
|
#
|
||||||
###############################################################################
|
###############################################################################
|
||||||
project(dbt-rise-tgc VERSION 1.0.0)
|
project(dbt-rise-tgc VERSION 1.0.0)
|
||||||
|
|
||||||
include(GNUInstallDirs)
|
include(GNUInstallDirs)
|
||||||
|
include(flink)
|
||||||
|
|
||||||
find_package(elfio QUIET)
|
find_package(elfio QUIET)
|
||||||
find_package(Boost COMPONENTS coroutine)
|
|
||||||
find_package(jsoncpp)
|
find_package(jsoncpp)
|
||||||
|
find_package(Boost COMPONENTS coroutine REQUIRED)
|
||||||
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)
|
|
||||||
|
|
||||||
add_subdirectory(softfloat)
|
add_subdirectory(softfloat)
|
||||||
|
|
||||||
set(LIB_SOURCES
|
set(LIB_SOURCES
|
||||||
src/iss/plugin/instruction_count.cpp
|
src/iss/plugin/instruction_count.cpp
|
||||||
src/iss/arch/tgc_c.cpp
|
src/iss/arch/tgc5c.cpp
|
||||||
src/vm/interp/vm_tgc_c.cpp
|
src/vm/interp/vm_tgc5c.cpp
|
||||||
src/vm/fp_functions.cpp
|
src/vm/fp_functions.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
|
# library files
|
||||||
if(TARGET ${CORE_NAME}_cpp)
|
|
||||||
list(APPEND LIB_SOURCES ${${CORE_NAME}_OUTPUT_FILES})
|
|
||||||
else()
|
|
||||||
FILE(GLOB GEN_ISS_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src-gen/iss/arch/*.cpp)
|
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_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})
|
list(APPEND LIB_SOURCES ${GEN_ISS_SOURCES} ${GEN_VM_SOURCES})
|
||||||
foreach(FILEPATH ${GEN_ISS_SOURCES})
|
foreach(FILEPATH ${GEN_ISS_SOURCES})
|
||||||
get_filename_component(CORE ${FILEPATH} NAME_WE)
|
get_filename_component(CORE ${FILEPATH} NAME_WE)
|
||||||
string(TOUPPER ${CORE} CORE)
|
string(TOUPPER ${CORE} CORE)
|
||||||
list(APPEND LIB_DEFINES CORE_${CORE})
|
list(APPEND LIB_DEFINES CORE_${CORE})
|
||||||
endforeach()
|
endforeach()
|
||||||
message("Defines are ${LIB_DEFINES}")
|
message(STATUS "Core defines are ${LIB_DEFINES}")
|
||||||
endif()
|
|
||||||
|
|
||||||
if(TARGET RapidJSON OR TARGET RapidJSON::RapidJSON)
|
|
||||||
list(APPEND LIB_SOURCES src/iss/plugin/cycle_estimate.cpp src/iss/plugin/pctrace.cpp)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(WITH_LLVM)
|
if(WITH_LLVM)
|
||||||
FILE(GLOB LLVM_GEN_SOURCES
|
FILE(GLOB LLVM_GEN_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src-gen/vm/llvm/vm_*.cpp)
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src-gen/vm/llvm/vm_*.cpp
|
|
||||||
)
|
|
||||||
list(APPEND LIB_SOURCES ${LLVM_GEN_SOURCES})
|
list(APPEND LIB_SOURCES ${LLVM_GEN_SOURCES})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(WITH_TCC)
|
if(WITH_TCC)
|
||||||
FILE(GLOB TCC_GEN_SOURCES
|
FILE(GLOB TCC_GEN_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src-gen/vm/tcc/vm_*.cpp)
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/vm/tcc/vm_*.cpp
|
|
||||||
)
|
|
||||||
list(APPEND LIB_SOURCES ${TCC_GEN_SOURCES})
|
list(APPEND LIB_SOURCES ${TCC_GEN_SOURCES})
|
||||||
endif()
|
endif()
|
||||||
|
if(WITH_ASMJIT)
|
||||||
# Define the library
|
FILE(GLOB TCC_GEN_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src-gen/vm/asmjit/vm_*.cpp)
|
||||||
add_library(${PROJECT_NAME} ${LIB_SOURCES})
|
list(APPEND LIB_SOURCES ${TCC_GEN_SOURCES})
|
||||||
# list code gen dependencies
|
|
||||||
if(TARGET ${CORE_NAME}_cpp)
|
|
||||||
add_dependencies(${PROJECT_NAME} ${CORE_NAME}_cpp)
|
|
||||||
endif()
|
endif()
|
||||||
|
if(TARGET yaml-cpp::yaml-cpp)
|
||||||
|
list(APPEND LIB_SOURCES
|
||||||
|
src/iss/plugin/cycle_estimate.cpp
|
||||||
|
src/iss/plugin/instruction_count.cpp
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
# Define the library
|
||||||
|
add_library(${PROJECT_NAME} SHARED ${LIB_SOURCES})
|
||||||
|
|
||||||
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
|
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
|
||||||
target_compile_options(${PROJECT_NAME} PRIVATE -Wno-shift-count-overflow)
|
target_compile_options(${PROJECT_NAME} PRIVATE -Wno-shift-count-overflow)
|
||||||
@@ -83,32 +77,30 @@ elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
|||||||
endif()
|
endif()
|
||||||
target_include_directories(${PROJECT_NAME} PUBLIC src)
|
target_include_directories(${PROJECT_NAME} PUBLIC src)
|
||||||
target_include_directories(${PROJECT_NAME} PUBLIC src-gen)
|
target_include_directories(${PROJECT_NAME} PUBLIC src-gen)
|
||||||
target_link_libraries(${PROJECT_NAME} PUBLIC softfloat scc-util Boost::coroutine)
|
|
||||||
if(TARGET jsoncpp::jsoncpp)
|
target_force_link_libraries(${PROJECT_NAME} PRIVATE dbt-rise-core)
|
||||||
target_link_libraries(${PROJECT_NAME} PUBLIC jsoncpp::jsoncpp)
|
# only re-export the include paths
|
||||||
else()
|
get_target_property(DBT_CORE_INCL dbt-rise-core INTERFACE_INCLUDE_DIRECTORIES)
|
||||||
target_link_libraries(${PROJECT_NAME} PUBLIC jsoncpp)
|
target_include_directories(${PROJECT_NAME} INTERFACE ${DBT_CORE_INCL})
|
||||||
endif()
|
get_target_property(DBT_CORE_DEFS dbt-rise-core INTERFACE_COMPILE_DEFINITIONS)
|
||||||
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" AND BUILD_SHARED_LIBS)
|
if(NOT (DBT_CORE_DEFS STREQUAL DBT_CORE_DEFS-NOTFOUND))
|
||||||
target_link_libraries(${PROJECT_NAME} PUBLIC -Wl,--whole-archive dbt-rise-core -Wl,--no-whole-archive)
|
target_compile_definitions(${PROJECT_NAME} INTERFACE ${DBT_CORE_DEFS})
|
||||||
else()
|
|
||||||
target_link_libraries(${PROJECT_NAME} PUBLIC dbt-rise-core)
|
|
||||||
endif()
|
|
||||||
if(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 lz4::lz4)
|
|
||||||
target_compile_definitions(${PROJECT_NAME} PUBLIC WITH_LZ4)
|
|
||||||
target_link_libraries(${PROJECT_NAME} PUBLIC lz4::lz4)
|
|
||||||
endif()
|
|
||||||
if(TARGET RapidJSON::RapidJSON)
|
|
||||||
target_link_libraries(${PROJECT_NAME} PUBLIC RapidJSON::RapidJSON)
|
|
||||||
elseif(TARGET RapidJSON)
|
|
||||||
target_link_libraries(${PROJECT_NAME} PUBLIC RapidJSON)
|
|
||||||
endif()
|
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
|
set_target_properties(${PROJECT_NAME} PROPERTIES
|
||||||
VERSION ${PROJECT_VERSION}
|
VERSION ${PROJECT_VERSION}
|
||||||
@@ -128,9 +120,11 @@ install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/incl/iss COMPONENT ${PROJECT_NAME}
|
|||||||
FILES_MATCHING # install only matched files
|
FILES_MATCHING # install only matched files
|
||||||
PATTERN "*.h" # select header 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)
|
project(tgc-sim)
|
||||||
find_package(Boost COMPONENTS program_options thread REQUIRED)
|
find_package(Boost COMPONENTS program_options thread REQUIRED)
|
||||||
|
|
||||||
@@ -153,15 +147,16 @@ foreach(F IN LISTS TGC_SOURCES)
|
|||||||
endif()
|
endif()
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
if(WITH_LLVM)
|
#if(WITH_LLVM)
|
||||||
target_compile_definitions(${PROJECT_NAME} PRIVATE WITH_LLVM)
|
# target_compile_definitions(${PROJECT_NAME} PRIVATE WITH_LLVM)
|
||||||
target_link_libraries(${PROJECT_NAME} PUBLIC ${llvm_libs})
|
# #target_link_libraries(${PROJECT_NAME} PUBLIC ${llvm_libs})
|
||||||
endif()
|
#endif()
|
||||||
if(WITH_TCC)
|
#if(WITH_TCC)
|
||||||
target_compile_definitions(${PROJECT_NAME} PRIVATE WITH_TCC)
|
# target_compile_definitions(${PROJECT_NAME} PRIVATE WITH_TCC)
|
||||||
endif()
|
#endif()
|
||||||
# Links the target exe against the libraries
|
|
||||||
target_link_libraries(${PROJECT_NAME} PUBLIC dbt-rise-tgc)
|
target_link_libraries(${PROJECT_NAME} PUBLIC dbt-rise-tgc fmt::fmt)
|
||||||
|
|
||||||
if(TARGET Boost::program_options)
|
if(TARGET Boost::program_options)
|
||||||
target_link_libraries(${PROJECT_NAME} PUBLIC Boost::program_options)
|
target_link_libraries(${PROJECT_NAME} PUBLIC Boost::program_options)
|
||||||
else()
|
else()
|
||||||
@@ -181,15 +176,36 @@ install(TARGETS tgc-sim
|
|||||||
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME} # headers for mac (note the different component -> different package)
|
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME} # headers for mac (note the different component -> different package)
|
||||||
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} # headers
|
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)
|
if(TARGET scc-sysc)
|
||||||
project(dbt-rise-tgc_sc VERSION 1.0.0)
|
project(dbt-rise-tgc_sc VERSION 1.0.0)
|
||||||
add_library(${PROJECT_NAME}
|
set(LIB_SOURCES
|
||||||
src/sysc/core_complex.cpp
|
src/sysc/core_complex.cpp
|
||||||
src/sysc/register_tgc_c.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} PUBLIC WITH_SYSTEMC)
|
||||||
target_compile_definitions(${PROJECT_NAME} PRIVATE CORE_${CORE_NAME})
|
target_compile_definitions(${PROJECT_NAME} PRIVATE CORE_${CORE_NAME})
|
||||||
foreach(F IN LISTS TGC_SOURCES)
|
foreach(F IN LISTS TGC_SOURCES)
|
||||||
@@ -200,9 +216,9 @@ if(TARGET scc-sysc)
|
|||||||
endif()
|
endif()
|
||||||
endforeach()
|
endforeach()
|
||||||
target_link_libraries(${PROJECT_NAME} PUBLIC dbt-rise-tgc scc-sysc)
|
target_link_libraries(${PROJECT_NAME} PUBLIC dbt-rise-tgc scc-sysc)
|
||||||
if(WITH_LLVM)
|
# if(WITH_LLVM)
|
||||||
target_link_libraries(${PROJECT_NAME} PUBLIC ${llvm_libs})
|
# target_link_libraries(${PROJECT_NAME} PUBLIC ${llvm_libs})
|
||||||
endif()
|
# endif()
|
||||||
|
|
||||||
set(LIB_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/src/sysc/core_complex.h)
|
set(LIB_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/src/sysc/core_complex.h)
|
||||||
set_target_properties(${PROJECT_NAME} PROPERTIES
|
set_target_properties(${PROJECT_NAME} PROPERTIES
|
||||||
|
|||||||
35
cmake/flink.cmake
Normal file
35
cmake/flink.cmake
Normal file
@@ -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()
|
||||||
1
contrib/instr/.gitignore
vendored
Normal file
1
contrib/instr/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
/*.yaml
|
||||||
@@ -1,307 +1,348 @@
|
|||||||
|
|
||||||
RV32I:
|
RVI:
|
||||||
- LUI:
|
LUI:
|
||||||
|
index: 0
|
||||||
encoding: 0b00000000000000000000000000110111
|
encoding: 0b00000000000000000000000000110111
|
||||||
mask: 0b00000000000000000000000001111111
|
mask: 0b00000000000000000000000001111111
|
||||||
size: 32
|
size: 32
|
||||||
branch: false
|
branch: false
|
||||||
delay: 1
|
delay: 1
|
||||||
- AUIPC:
|
AUIPC:
|
||||||
|
index: 1
|
||||||
encoding: 0b00000000000000000000000000010111
|
encoding: 0b00000000000000000000000000010111
|
||||||
mask: 0b00000000000000000000000001111111
|
mask: 0b00000000000000000000000001111111
|
||||||
size: 32
|
size: 32
|
||||||
branch: false
|
branch: false
|
||||||
delay: 1
|
delay: 1
|
||||||
- JAL:
|
JAL:
|
||||||
|
index: 2
|
||||||
encoding: 0b00000000000000000000000001101111
|
encoding: 0b00000000000000000000000001101111
|
||||||
mask: 0b00000000000000000000000001111111
|
mask: 0b00000000000000000000000001111111
|
||||||
attributes: [[name:no_cont]]
|
|
||||||
size: 32
|
size: 32
|
||||||
branch: true
|
branch: true
|
||||||
delay: 1
|
delay: 1
|
||||||
- JALR:
|
JALR:
|
||||||
|
index: 3
|
||||||
encoding: 0b00000000000000000000000001100111
|
encoding: 0b00000000000000000000000001100111
|
||||||
mask: 0b00000000000000000111000001111111
|
mask: 0b00000000000000000111000001111111
|
||||||
attributes: [[name:no_cont]]
|
|
||||||
size: 32
|
size: 32
|
||||||
branch: true
|
branch: true
|
||||||
delay: 1
|
delay: [1,1]
|
||||||
- BEQ:
|
BEQ:
|
||||||
|
index: 4
|
||||||
encoding: 0b00000000000000000000000001100011
|
encoding: 0b00000000000000000000000001100011
|
||||||
mask: 0b00000000000000000111000001111111
|
mask: 0b00000000000000000111000001111111
|
||||||
attributes: [[name:no_cont], [name:cond]]
|
|
||||||
size: 32
|
size: 32
|
||||||
branch: true
|
branch: true
|
||||||
delay: [1,1]
|
delay: [1,1]
|
||||||
- BNE:
|
BNE:
|
||||||
|
index: 5
|
||||||
encoding: 0b00000000000000000001000001100011
|
encoding: 0b00000000000000000001000001100011
|
||||||
mask: 0b00000000000000000111000001111111
|
mask: 0b00000000000000000111000001111111
|
||||||
attributes: [[name:no_cont], [name:cond]]
|
|
||||||
size: 32
|
size: 32
|
||||||
branch: true
|
branch: true
|
||||||
delay: [1,1]
|
delay: [1,1]
|
||||||
- BLT:
|
BLT:
|
||||||
|
index: 6
|
||||||
encoding: 0b00000000000000000100000001100011
|
encoding: 0b00000000000000000100000001100011
|
||||||
mask: 0b00000000000000000111000001111111
|
mask: 0b00000000000000000111000001111111
|
||||||
attributes: [[name:no_cont], [name:cond]]
|
|
||||||
size: 32
|
size: 32
|
||||||
branch: true
|
branch: true
|
||||||
delay: [1,1]
|
delay: [1,1]
|
||||||
- BGE:
|
BGE:
|
||||||
|
index: 7
|
||||||
encoding: 0b00000000000000000101000001100011
|
encoding: 0b00000000000000000101000001100011
|
||||||
mask: 0b00000000000000000111000001111111
|
mask: 0b00000000000000000111000001111111
|
||||||
attributes: [[name:no_cont], [name:cond]]
|
|
||||||
size: 32
|
size: 32
|
||||||
branch: true
|
branch: true
|
||||||
delay: [1,1]
|
delay: [1,1]
|
||||||
- BLTU:
|
BLTU:
|
||||||
|
index: 8
|
||||||
encoding: 0b00000000000000000110000001100011
|
encoding: 0b00000000000000000110000001100011
|
||||||
mask: 0b00000000000000000111000001111111
|
mask: 0b00000000000000000111000001111111
|
||||||
attributes: [[name:no_cont], [name:cond]]
|
|
||||||
size: 32
|
size: 32
|
||||||
branch: true
|
branch: true
|
||||||
delay: [1,1]
|
delay: [1,1]
|
||||||
- BGEU:
|
BGEU:
|
||||||
|
index: 9
|
||||||
encoding: 0b00000000000000000111000001100011
|
encoding: 0b00000000000000000111000001100011
|
||||||
mask: 0b00000000000000000111000001111111
|
mask: 0b00000000000000000111000001111111
|
||||||
attributes: [[name:no_cont], [name:cond]]
|
|
||||||
size: 32
|
size: 32
|
||||||
branch: true
|
branch: true
|
||||||
delay: [1,1]
|
delay: [1,1]
|
||||||
- LB:
|
LB:
|
||||||
|
index: 10
|
||||||
encoding: 0b00000000000000000000000000000011
|
encoding: 0b00000000000000000000000000000011
|
||||||
mask: 0b00000000000000000111000001111111
|
mask: 0b00000000000000000111000001111111
|
||||||
size: 32
|
size: 32
|
||||||
branch: false
|
branch: false
|
||||||
delay: 1
|
delay: 1
|
||||||
- LH:
|
LH:
|
||||||
|
index: 11
|
||||||
encoding: 0b00000000000000000001000000000011
|
encoding: 0b00000000000000000001000000000011
|
||||||
mask: 0b00000000000000000111000001111111
|
mask: 0b00000000000000000111000001111111
|
||||||
size: 32
|
size: 32
|
||||||
branch: false
|
branch: false
|
||||||
delay: 1
|
delay: 1
|
||||||
- LW:
|
LW:
|
||||||
|
index: 12
|
||||||
encoding: 0b00000000000000000010000000000011
|
encoding: 0b00000000000000000010000000000011
|
||||||
mask: 0b00000000000000000111000001111111
|
mask: 0b00000000000000000111000001111111
|
||||||
size: 32
|
size: 32
|
||||||
branch: false
|
branch: false
|
||||||
delay: 1
|
delay: 1
|
||||||
- LBU:
|
LBU:
|
||||||
|
index: 13
|
||||||
encoding: 0b00000000000000000100000000000011
|
encoding: 0b00000000000000000100000000000011
|
||||||
mask: 0b00000000000000000111000001111111
|
mask: 0b00000000000000000111000001111111
|
||||||
size: 32
|
size: 32
|
||||||
branch: false
|
branch: false
|
||||||
delay: 1
|
delay: 1
|
||||||
- LHU:
|
LHU:
|
||||||
|
index: 14
|
||||||
encoding: 0b00000000000000000101000000000011
|
encoding: 0b00000000000000000101000000000011
|
||||||
mask: 0b00000000000000000111000001111111
|
mask: 0b00000000000000000111000001111111
|
||||||
size: 32
|
size: 32
|
||||||
branch: false
|
branch: false
|
||||||
delay: 1
|
delay: 1
|
||||||
- SB:
|
SB:
|
||||||
|
index: 15
|
||||||
encoding: 0b00000000000000000000000000100011
|
encoding: 0b00000000000000000000000000100011
|
||||||
mask: 0b00000000000000000111000001111111
|
mask: 0b00000000000000000111000001111111
|
||||||
size: 32
|
size: 32
|
||||||
branch: false
|
branch: false
|
||||||
delay: 1
|
delay: 1
|
||||||
- SH:
|
SH:
|
||||||
|
index: 16
|
||||||
encoding: 0b00000000000000000001000000100011
|
encoding: 0b00000000000000000001000000100011
|
||||||
mask: 0b00000000000000000111000001111111
|
mask: 0b00000000000000000111000001111111
|
||||||
size: 32
|
size: 32
|
||||||
branch: false
|
branch: false
|
||||||
delay: 1
|
delay: 1
|
||||||
- SW:
|
SW:
|
||||||
|
index: 17
|
||||||
encoding: 0b00000000000000000010000000100011
|
encoding: 0b00000000000000000010000000100011
|
||||||
mask: 0b00000000000000000111000001111111
|
mask: 0b00000000000000000111000001111111
|
||||||
size: 32
|
size: 32
|
||||||
branch: false
|
branch: false
|
||||||
delay: 1
|
delay: 1
|
||||||
- ADDI:
|
ADDI:
|
||||||
|
index: 18
|
||||||
encoding: 0b00000000000000000000000000010011
|
encoding: 0b00000000000000000000000000010011
|
||||||
mask: 0b00000000000000000111000001111111
|
mask: 0b00000000000000000111000001111111
|
||||||
size: 32
|
size: 32
|
||||||
branch: false
|
branch: false
|
||||||
delay: 1
|
delay: 1
|
||||||
- SLTI:
|
SLTI:
|
||||||
|
index: 19
|
||||||
encoding: 0b00000000000000000010000000010011
|
encoding: 0b00000000000000000010000000010011
|
||||||
mask: 0b00000000000000000111000001111111
|
mask: 0b00000000000000000111000001111111
|
||||||
size: 32
|
size: 32
|
||||||
branch: false
|
branch: false
|
||||||
delay: 1
|
delay: 1
|
||||||
- SLTIU:
|
SLTIU:
|
||||||
|
index: 20
|
||||||
encoding: 0b00000000000000000011000000010011
|
encoding: 0b00000000000000000011000000010011
|
||||||
mask: 0b00000000000000000111000001111111
|
mask: 0b00000000000000000111000001111111
|
||||||
size: 32
|
size: 32
|
||||||
branch: false
|
branch: false
|
||||||
delay: 1
|
delay: 1
|
||||||
- XORI:
|
XORI:
|
||||||
|
index: 21
|
||||||
encoding: 0b00000000000000000100000000010011
|
encoding: 0b00000000000000000100000000010011
|
||||||
mask: 0b00000000000000000111000001111111
|
mask: 0b00000000000000000111000001111111
|
||||||
size: 32
|
size: 32
|
||||||
branch: false
|
branch: false
|
||||||
delay: 1
|
delay: 1
|
||||||
- ORI:
|
ORI:
|
||||||
|
index: 22
|
||||||
encoding: 0b00000000000000000110000000010011
|
encoding: 0b00000000000000000110000000010011
|
||||||
mask: 0b00000000000000000111000001111111
|
mask: 0b00000000000000000111000001111111
|
||||||
size: 32
|
size: 32
|
||||||
branch: false
|
branch: false
|
||||||
delay: 1
|
delay: 1
|
||||||
- ANDI:
|
ANDI:
|
||||||
|
index: 23
|
||||||
encoding: 0b00000000000000000111000000010011
|
encoding: 0b00000000000000000111000000010011
|
||||||
mask: 0b00000000000000000111000001111111
|
mask: 0b00000000000000000111000001111111
|
||||||
size: 32
|
size: 32
|
||||||
branch: false
|
branch: false
|
||||||
delay: 1
|
delay: 1
|
||||||
- SLLI:
|
SLLI:
|
||||||
|
index: 24
|
||||||
encoding: 0b00000000000000000001000000010011
|
encoding: 0b00000000000000000001000000010011
|
||||||
mask: 0b11111110000000000111000001111111
|
mask: 0b11111110000000000111000001111111
|
||||||
size: 32
|
size: 32
|
||||||
branch: false
|
branch: false
|
||||||
delay: 1
|
delay: 1
|
||||||
- SRLI:
|
SRLI:
|
||||||
|
index: 25
|
||||||
encoding: 0b00000000000000000101000000010011
|
encoding: 0b00000000000000000101000000010011
|
||||||
mask: 0b11111110000000000111000001111111
|
mask: 0b11111110000000000111000001111111
|
||||||
size: 32
|
size: 32
|
||||||
branch: false
|
branch: false
|
||||||
delay: 1
|
delay: 1
|
||||||
- SRAI:
|
SRAI:
|
||||||
|
index: 26
|
||||||
encoding: 0b01000000000000000101000000010011
|
encoding: 0b01000000000000000101000000010011
|
||||||
mask: 0b11111110000000000111000001111111
|
mask: 0b11111110000000000111000001111111
|
||||||
size: 32
|
size: 32
|
||||||
branch: false
|
branch: false
|
||||||
delay: 1
|
delay: 1
|
||||||
- ADD:
|
ADD:
|
||||||
|
index: 27
|
||||||
encoding: 0b00000000000000000000000000110011
|
encoding: 0b00000000000000000000000000110011
|
||||||
mask: 0b11111110000000000111000001111111
|
mask: 0b11111110000000000111000001111111
|
||||||
size: 32
|
size: 32
|
||||||
branch: false
|
branch: false
|
||||||
delay: 1
|
delay: 1
|
||||||
- SUB:
|
SUB:
|
||||||
|
index: 28
|
||||||
encoding: 0b01000000000000000000000000110011
|
encoding: 0b01000000000000000000000000110011
|
||||||
mask: 0b11111110000000000111000001111111
|
mask: 0b11111110000000000111000001111111
|
||||||
size: 32
|
size: 32
|
||||||
branch: false
|
branch: false
|
||||||
delay: 1
|
delay: 1
|
||||||
- SLL:
|
SLL:
|
||||||
|
index: 29
|
||||||
encoding: 0b00000000000000000001000000110011
|
encoding: 0b00000000000000000001000000110011
|
||||||
mask: 0b11111110000000000111000001111111
|
mask: 0b11111110000000000111000001111111
|
||||||
size: 32
|
size: 32
|
||||||
branch: false
|
branch: false
|
||||||
delay: 1
|
delay: 1
|
||||||
- SLT:
|
SLT:
|
||||||
|
index: 30
|
||||||
encoding: 0b00000000000000000010000000110011
|
encoding: 0b00000000000000000010000000110011
|
||||||
mask: 0b11111110000000000111000001111111
|
mask: 0b11111110000000000111000001111111
|
||||||
size: 32
|
size: 32
|
||||||
branch: false
|
branch: false
|
||||||
delay: 1
|
delay: 1
|
||||||
- SLTU:
|
SLTU:
|
||||||
|
index: 31
|
||||||
encoding: 0b00000000000000000011000000110011
|
encoding: 0b00000000000000000011000000110011
|
||||||
mask: 0b11111110000000000111000001111111
|
mask: 0b11111110000000000111000001111111
|
||||||
size: 32
|
size: 32
|
||||||
branch: false
|
branch: false
|
||||||
delay: 1
|
delay: 1
|
||||||
- XOR:
|
XOR:
|
||||||
|
index: 32
|
||||||
encoding: 0b00000000000000000100000000110011
|
encoding: 0b00000000000000000100000000110011
|
||||||
mask: 0b11111110000000000111000001111111
|
mask: 0b11111110000000000111000001111111
|
||||||
size: 32
|
size: 32
|
||||||
branch: false
|
branch: false
|
||||||
delay: 1
|
delay: 1
|
||||||
- SRL:
|
SRL:
|
||||||
|
index: 33
|
||||||
encoding: 0b00000000000000000101000000110011
|
encoding: 0b00000000000000000101000000110011
|
||||||
mask: 0b11111110000000000111000001111111
|
mask: 0b11111110000000000111000001111111
|
||||||
size: 32
|
size: 32
|
||||||
branch: false
|
branch: false
|
||||||
delay: 1
|
delay: 1
|
||||||
- SRA:
|
SRA:
|
||||||
|
index: 34
|
||||||
encoding: 0b01000000000000000101000000110011
|
encoding: 0b01000000000000000101000000110011
|
||||||
mask: 0b11111110000000000111000001111111
|
mask: 0b11111110000000000111000001111111
|
||||||
size: 32
|
size: 32
|
||||||
branch: false
|
branch: false
|
||||||
delay: 1
|
delay: 1
|
||||||
- OR:
|
OR:
|
||||||
|
index: 35
|
||||||
encoding: 0b00000000000000000110000000110011
|
encoding: 0b00000000000000000110000000110011
|
||||||
mask: 0b11111110000000000111000001111111
|
mask: 0b11111110000000000111000001111111
|
||||||
size: 32
|
size: 32
|
||||||
branch: false
|
branch: false
|
||||||
delay: 1
|
delay: 1
|
||||||
- AND:
|
AND:
|
||||||
|
index: 36
|
||||||
encoding: 0b00000000000000000111000000110011
|
encoding: 0b00000000000000000111000000110011
|
||||||
mask: 0b11111110000000000111000001111111
|
mask: 0b11111110000000000111000001111111
|
||||||
size: 32
|
size: 32
|
||||||
branch: false
|
branch: false
|
||||||
delay: 1
|
delay: 1
|
||||||
- FENCE:
|
FENCE:
|
||||||
|
index: 37
|
||||||
encoding: 0b00000000000000000000000000001111
|
encoding: 0b00000000000000000000000000001111
|
||||||
mask: 0b00000000000000000111000001111111
|
mask: 0b00000000000000000111000001111111
|
||||||
size: 32
|
size: 32
|
||||||
branch: false
|
branch: false
|
||||||
delay: 1
|
delay: 1
|
||||||
- ECALL:
|
ECALL:
|
||||||
|
index: 38
|
||||||
encoding: 0b00000000000000000000000001110011
|
encoding: 0b00000000000000000000000001110011
|
||||||
mask: 0b11111111111111111111111111111111
|
mask: 0b11111111111111111111111111111111
|
||||||
attributes: [[name:no_cont]]
|
attributes: [[name:no_cont]]
|
||||||
size: 32
|
size: 32
|
||||||
branch: false
|
branch: false
|
||||||
delay: 1
|
delay: 1
|
||||||
- EBREAK:
|
EBREAK:
|
||||||
|
index: 39
|
||||||
encoding: 0b00000000000100000000000001110011
|
encoding: 0b00000000000100000000000001110011
|
||||||
mask: 0b11111111111111111111111111111111
|
mask: 0b11111111111111111111111111111111
|
||||||
attributes: [[name:no_cont]]
|
attributes: [[name:no_cont]]
|
||||||
size: 32
|
size: 32
|
||||||
branch: false
|
branch: false
|
||||||
delay: 1
|
delay: 1
|
||||||
- MRET:
|
MRET:
|
||||||
|
index: 40
|
||||||
encoding: 0b00110000001000000000000001110011
|
encoding: 0b00110000001000000000000001110011
|
||||||
mask: 0b11111111111111111111111111111111
|
mask: 0b11111111111111111111111111111111
|
||||||
attributes: [[name:no_cont]]
|
attributes: [[name:no_cont]]
|
||||||
size: 32
|
size: 32
|
||||||
branch: false
|
branch: false
|
||||||
delay: 1
|
delay: 1
|
||||||
- WFI:
|
WFI:
|
||||||
|
index: 41
|
||||||
encoding: 0b00010000010100000000000001110011
|
encoding: 0b00010000010100000000000001110011
|
||||||
mask: 0b11111111111111111111111111111111
|
mask: 0b11111111111111111111111111111111
|
||||||
size: 32
|
size: 32
|
||||||
branch: false
|
branch: false
|
||||||
delay: 1
|
delay: 1
|
||||||
Zicsr:
|
Zicsr:
|
||||||
- CSRRW:
|
CSRRW:
|
||||||
|
index: 42
|
||||||
encoding: 0b00000000000000000001000001110011
|
encoding: 0b00000000000000000001000001110011
|
||||||
mask: 0b00000000000000000111000001111111
|
mask: 0b00000000000000000111000001111111
|
||||||
size: 32
|
size: 32
|
||||||
branch: false
|
branch: false
|
||||||
delay: 1
|
delay: 1
|
||||||
- CSRRS:
|
CSRRS:
|
||||||
|
index: 43
|
||||||
encoding: 0b00000000000000000010000001110011
|
encoding: 0b00000000000000000010000001110011
|
||||||
mask: 0b00000000000000000111000001111111
|
mask: 0b00000000000000000111000001111111
|
||||||
size: 32
|
size: 32
|
||||||
branch: false
|
branch: false
|
||||||
delay: 1
|
delay: 1
|
||||||
- CSRRC:
|
CSRRC:
|
||||||
|
index: 44
|
||||||
encoding: 0b00000000000000000011000001110011
|
encoding: 0b00000000000000000011000001110011
|
||||||
mask: 0b00000000000000000111000001111111
|
mask: 0b00000000000000000111000001111111
|
||||||
size: 32
|
size: 32
|
||||||
branch: false
|
branch: false
|
||||||
delay: 1
|
delay: 1
|
||||||
- CSRRWI:
|
CSRRWI:
|
||||||
|
index: 45
|
||||||
encoding: 0b00000000000000000101000001110011
|
encoding: 0b00000000000000000101000001110011
|
||||||
mask: 0b00000000000000000111000001111111
|
mask: 0b00000000000000000111000001111111
|
||||||
size: 32
|
size: 32
|
||||||
branch: false
|
branch: false
|
||||||
delay: 1
|
delay: 1
|
||||||
- CSRRSI:
|
CSRRSI:
|
||||||
|
index: 46
|
||||||
encoding: 0b00000000000000000110000001110011
|
encoding: 0b00000000000000000110000001110011
|
||||||
mask: 0b00000000000000000111000001111111
|
mask: 0b00000000000000000111000001111111
|
||||||
size: 32
|
size: 32
|
||||||
branch: false
|
branch: false
|
||||||
delay: 1
|
delay: 1
|
||||||
- CSRRCI:
|
CSRRCI:
|
||||||
|
index: 47
|
||||||
encoding: 0b00000000000000000111000001110011
|
encoding: 0b00000000000000000111000001110011
|
||||||
mask: 0b00000000000000000111000001111111
|
mask: 0b00000000000000000111000001111111
|
||||||
size: 32
|
size: 32
|
||||||
branch: false
|
branch: false
|
||||||
delay: 1
|
delay: 1
|
||||||
Zifencei:
|
Zifencei:
|
||||||
- FENCE_I:
|
FENCE_I:
|
||||||
|
index: 48
|
||||||
encoding: 0b00000000000000000001000000001111
|
encoding: 0b00000000000000000001000000001111
|
||||||
mask: 0b00000000000000000111000001111111
|
mask: 0b00000000000000000111000001111111
|
||||||
attributes: [[name:flush]]
|
attributes: [[name:flush]]
|
||||||
@@ -309,228 +350,274 @@ Zifencei:
|
|||||||
branch: false
|
branch: false
|
||||||
delay: 1
|
delay: 1
|
||||||
RV32M:
|
RV32M:
|
||||||
- MUL:
|
MUL:
|
||||||
|
index: 49
|
||||||
encoding: 0b00000010000000000000000000110011
|
encoding: 0b00000010000000000000000000110011
|
||||||
mask: 0b11111110000000000111000001111111
|
mask: 0b11111110000000000111000001111111
|
||||||
size: 32
|
size: 32
|
||||||
branch: false
|
branch: false
|
||||||
delay: 1
|
delay: 1
|
||||||
- MULH:
|
MULH:
|
||||||
|
index: 50
|
||||||
encoding: 0b00000010000000000001000000110011
|
encoding: 0b00000010000000000001000000110011
|
||||||
mask: 0b11111110000000000111000001111111
|
mask: 0b11111110000000000111000001111111
|
||||||
size: 32
|
size: 32
|
||||||
branch: false
|
branch: false
|
||||||
delay: 1
|
delay: 1
|
||||||
- MULHSU:
|
MULHSU:
|
||||||
|
index: 51
|
||||||
encoding: 0b00000010000000000010000000110011
|
encoding: 0b00000010000000000010000000110011
|
||||||
mask: 0b11111110000000000111000001111111
|
mask: 0b11111110000000000111000001111111
|
||||||
size: 32
|
size: 32
|
||||||
branch: false
|
branch: false
|
||||||
delay: 1
|
delay: 1
|
||||||
- MULHU:
|
MULHU:
|
||||||
|
index: 52
|
||||||
encoding: 0b00000010000000000011000000110011
|
encoding: 0b00000010000000000011000000110011
|
||||||
mask: 0b11111110000000000111000001111111
|
mask: 0b11111110000000000111000001111111
|
||||||
size: 32
|
size: 32
|
||||||
branch: false
|
branch: false
|
||||||
delay: 1
|
delay: 1
|
||||||
- DIV:
|
DIV:
|
||||||
|
index: 53
|
||||||
encoding: 0b00000010000000000100000000110011
|
encoding: 0b00000010000000000100000000110011
|
||||||
mask: 0b11111110000000000111000001111111
|
mask: 0b11111110000000000111000001111111
|
||||||
size: 32
|
size: 32
|
||||||
branch: false
|
branch: false
|
||||||
delay: 1
|
delay: 1
|
||||||
- DIVU:
|
DIVU:
|
||||||
|
index: 54
|
||||||
encoding: 0b00000010000000000101000000110011
|
encoding: 0b00000010000000000101000000110011
|
||||||
mask: 0b11111110000000000111000001111111
|
mask: 0b11111110000000000111000001111111
|
||||||
size: 32
|
size: 32
|
||||||
branch: false
|
branch: false
|
||||||
delay: 1
|
delay: 1
|
||||||
- REM:
|
REM:
|
||||||
|
index: 55
|
||||||
encoding: 0b00000010000000000110000000110011
|
encoding: 0b00000010000000000110000000110011
|
||||||
mask: 0b11111110000000000111000001111111
|
mask: 0b11111110000000000111000001111111
|
||||||
size: 32
|
size: 32
|
||||||
branch: false
|
branch: false
|
||||||
delay: 1
|
delay: 1
|
||||||
- REMU:
|
REMU:
|
||||||
|
index: 56
|
||||||
encoding: 0b00000010000000000111000000110011
|
encoding: 0b00000010000000000111000000110011
|
||||||
mask: 0b11111110000000000111000001111111
|
mask: 0b11111110000000000111000001111111
|
||||||
size: 32
|
size: 32
|
||||||
branch: false
|
branch: false
|
||||||
delay: 1
|
delay: 1
|
||||||
RV32IC:
|
Zca:
|
||||||
- CADDI4SPN:
|
C__ADDI4SPN:
|
||||||
|
index: 57
|
||||||
encoding: 0b0000000000000000
|
encoding: 0b0000000000000000
|
||||||
mask: 0b1110000000000011
|
mask: 0b1110000000000011
|
||||||
size: 16
|
size: 16
|
||||||
branch: false
|
branch: false
|
||||||
delay: 1
|
delay: 1
|
||||||
- CLW:
|
C__LW:
|
||||||
|
index: 58
|
||||||
encoding: 0b0100000000000000
|
encoding: 0b0100000000000000
|
||||||
mask: 0b1110000000000011
|
mask: 0b1110000000000011
|
||||||
size: 16
|
size: 16
|
||||||
branch: false
|
branch: false
|
||||||
delay: 1
|
delay: 1
|
||||||
- CSW:
|
C__SW:
|
||||||
|
index: 59
|
||||||
encoding: 0b1100000000000000
|
encoding: 0b1100000000000000
|
||||||
mask: 0b1110000000000011
|
mask: 0b1110000000000011
|
||||||
size: 16
|
size: 16
|
||||||
branch: false
|
branch: false
|
||||||
delay: 1
|
delay: 1
|
||||||
- CADDI:
|
C__ADDI:
|
||||||
|
index: 60
|
||||||
encoding: 0b0000000000000001
|
encoding: 0b0000000000000001
|
||||||
mask: 0b1110000000000011
|
mask: 0b1110000000000011
|
||||||
size: 16
|
size: 16
|
||||||
branch: false
|
branch: false
|
||||||
delay: 1
|
delay: 1
|
||||||
- CNOP:
|
C__NOP:
|
||||||
|
index: 61
|
||||||
encoding: 0b0000000000000001
|
encoding: 0b0000000000000001
|
||||||
mask: 0b1110111110000011
|
mask: 0b1110111110000011
|
||||||
size: 16
|
size: 16
|
||||||
branch: false
|
branch: false
|
||||||
delay: 1
|
delay: 1
|
||||||
- CJAL:
|
C__JAL:
|
||||||
|
index: 62
|
||||||
encoding: 0b0010000000000001
|
encoding: 0b0010000000000001
|
||||||
mask: 0b1110000000000011
|
mask: 0b1110000000000011
|
||||||
attributes: [[name:no_cont]]
|
attributes: [[name:enable, value:1]]
|
||||||
size: 16
|
size: 16
|
||||||
branch: true
|
branch: true
|
||||||
delay: 1
|
delay: 1
|
||||||
- CLI:
|
C__LI:
|
||||||
|
index: 63
|
||||||
encoding: 0b0100000000000001
|
encoding: 0b0100000000000001
|
||||||
mask: 0b1110000000000011
|
mask: 0b1110000000000011
|
||||||
size: 16
|
size: 16
|
||||||
branch: false
|
branch: false
|
||||||
delay: 1
|
delay: 1
|
||||||
- CLUI:
|
C__LUI:
|
||||||
|
index: 64
|
||||||
encoding: 0b0110000000000001
|
encoding: 0b0110000000000001
|
||||||
mask: 0b1110000000000011
|
mask: 0b1110000000000011
|
||||||
size: 16
|
size: 16
|
||||||
branch: false
|
branch: false
|
||||||
delay: 1
|
delay: 1
|
||||||
- CADDI16SP:
|
C__ADDI16SP:
|
||||||
|
index: 65
|
||||||
encoding: 0b0110000100000001
|
encoding: 0b0110000100000001
|
||||||
mask: 0b1110111110000011
|
mask: 0b1110111110000011
|
||||||
size: 16
|
size: 16
|
||||||
branch: false
|
branch: false
|
||||||
delay: 1
|
delay: 1
|
||||||
- CSRLI:
|
__reserved_clui:
|
||||||
|
index: 66
|
||||||
|
encoding: 0b0110000000000001
|
||||||
|
mask: 0b1111000001111111
|
||||||
|
size: 16
|
||||||
|
branch: false
|
||||||
|
delay: 1
|
||||||
|
C__SRLI:
|
||||||
|
index: 67
|
||||||
encoding: 0b1000000000000001
|
encoding: 0b1000000000000001
|
||||||
mask: 0b1111110000000011
|
mask: 0b1111110000000011
|
||||||
|
attributes: [[name:enable, value:1]]
|
||||||
size: 16
|
size: 16
|
||||||
branch: false
|
branch: false
|
||||||
delay: 1
|
delay: 1
|
||||||
- CSRAI:
|
C__SRAI:
|
||||||
|
index: 68
|
||||||
encoding: 0b1000010000000001
|
encoding: 0b1000010000000001
|
||||||
mask: 0b1111110000000011
|
mask: 0b1111110000000011
|
||||||
|
attributes: [[name:enable, value:1]]
|
||||||
size: 16
|
size: 16
|
||||||
branch: false
|
branch: false
|
||||||
delay: 1
|
delay: 1
|
||||||
- CANDI:
|
C__ANDI:
|
||||||
|
index: 69
|
||||||
encoding: 0b1000100000000001
|
encoding: 0b1000100000000001
|
||||||
mask: 0b1110110000000011
|
mask: 0b1110110000000011
|
||||||
size: 16
|
size: 16
|
||||||
branch: false
|
branch: false
|
||||||
delay: 1
|
delay: 1
|
||||||
- CSUB:
|
C__SUB:
|
||||||
|
index: 70
|
||||||
encoding: 0b1000110000000001
|
encoding: 0b1000110000000001
|
||||||
mask: 0b1111110001100011
|
mask: 0b1111110001100011
|
||||||
size: 16
|
size: 16
|
||||||
branch: false
|
branch: false
|
||||||
delay: 1
|
delay: 1
|
||||||
- CXOR:
|
C__XOR:
|
||||||
|
index: 71
|
||||||
encoding: 0b1000110000100001
|
encoding: 0b1000110000100001
|
||||||
mask: 0b1111110001100011
|
mask: 0b1111110001100011
|
||||||
size: 16
|
size: 16
|
||||||
branch: false
|
branch: false
|
||||||
delay: 1
|
delay: 1
|
||||||
- COR:
|
C__OR:
|
||||||
|
index: 72
|
||||||
encoding: 0b1000110001000001
|
encoding: 0b1000110001000001
|
||||||
mask: 0b1111110001100011
|
mask: 0b1111110001100011
|
||||||
size: 16
|
size: 16
|
||||||
branch: false
|
branch: false
|
||||||
delay: 1
|
delay: 1
|
||||||
- CAND:
|
C__AND:
|
||||||
|
index: 73
|
||||||
encoding: 0b1000110001100001
|
encoding: 0b1000110001100001
|
||||||
mask: 0b1111110001100011
|
mask: 0b1111110001100011
|
||||||
size: 16
|
size: 16
|
||||||
branch: false
|
branch: false
|
||||||
delay: 1
|
delay: 1
|
||||||
- CJ:
|
C__J:
|
||||||
|
index: 74
|
||||||
encoding: 0b1010000000000001
|
encoding: 0b1010000000000001
|
||||||
mask: 0b1110000000000011
|
mask: 0b1110000000000011
|
||||||
attributes: [[name:no_cont]]
|
|
||||||
size: 16
|
size: 16
|
||||||
branch: true
|
branch: true
|
||||||
delay: 1
|
delay: 1
|
||||||
- CBEQZ:
|
C__BEQZ:
|
||||||
|
index: 75
|
||||||
encoding: 0b1100000000000001
|
encoding: 0b1100000000000001
|
||||||
mask: 0b1110000000000011
|
mask: 0b1110000000000011
|
||||||
attributes: [[name:no_cont], [name:cond]]
|
|
||||||
size: 16
|
size: 16
|
||||||
branch: true
|
branch: true
|
||||||
delay: [1,1]
|
delay: [1,1]
|
||||||
- CBNEZ:
|
C__BNEZ:
|
||||||
|
index: 76
|
||||||
encoding: 0b1110000000000001
|
encoding: 0b1110000000000001
|
||||||
mask: 0b1110000000000011
|
mask: 0b1110000000000011
|
||||||
attributes: [[name:no_cont], [name:cond]]
|
|
||||||
size: 16
|
size: 16
|
||||||
branch: true
|
branch: true
|
||||||
delay: [1,1]
|
delay: [1,1]
|
||||||
- CSLLI:
|
C__SLLI:
|
||||||
|
index: 77
|
||||||
encoding: 0b0000000000000010
|
encoding: 0b0000000000000010
|
||||||
mask: 0b1111000000000011
|
mask: 0b1111000000000011
|
||||||
|
attributes: [[name:enable, value:1]]
|
||||||
size: 16
|
size: 16
|
||||||
branch: false
|
branch: false
|
||||||
delay: 1
|
delay: 1
|
||||||
- CLWSP:
|
C__LWSP:
|
||||||
|
index: 78
|
||||||
encoding: 0b0100000000000010
|
encoding: 0b0100000000000010
|
||||||
mask: 0b1110000000000011
|
mask: 0b1110000000000011
|
||||||
size: 16
|
size: 16
|
||||||
branch: false
|
branch: false
|
||||||
delay: 1
|
delay: 1
|
||||||
- CMV:
|
C__MV:
|
||||||
|
index: 79
|
||||||
encoding: 0b1000000000000010
|
encoding: 0b1000000000000010
|
||||||
mask: 0b1111000000000011
|
mask: 0b1111000000000011
|
||||||
size: 16
|
size: 16
|
||||||
branch: false
|
branch: false
|
||||||
delay: 1
|
delay: 1
|
||||||
- CJR:
|
C__JR:
|
||||||
|
index: 80
|
||||||
encoding: 0b1000000000000010
|
encoding: 0b1000000000000010
|
||||||
mask: 0b1111000001111111
|
mask: 0b1111000001111111
|
||||||
attributes: [[name:no_cont]]
|
|
||||||
size: 16
|
size: 16
|
||||||
branch: true
|
branch: true
|
||||||
delay: 1
|
delay: 1
|
||||||
- CADD:
|
__reserved_cmv:
|
||||||
|
index: 81
|
||||||
|
encoding: 0b1000000000000010
|
||||||
|
mask: 0b1111111111111111
|
||||||
|
size: 16
|
||||||
|
branch: false
|
||||||
|
delay: 1
|
||||||
|
C__ADD:
|
||||||
|
index: 82
|
||||||
encoding: 0b1001000000000010
|
encoding: 0b1001000000000010
|
||||||
mask: 0b1111000000000011
|
mask: 0b1111000000000011
|
||||||
size: 16
|
size: 16
|
||||||
branch: false
|
branch: false
|
||||||
delay: 1
|
delay: 1
|
||||||
- CJALR:
|
C__JALR:
|
||||||
|
index: 83
|
||||||
encoding: 0b1001000000000010
|
encoding: 0b1001000000000010
|
||||||
mask: 0b1111000001111111
|
mask: 0b1111000001111111
|
||||||
attributes: [[name:no_cont]]
|
|
||||||
size: 16
|
size: 16
|
||||||
branch: true
|
branch: true
|
||||||
delay: 1
|
delay: 1
|
||||||
- CEBREAK:
|
C__EBREAK:
|
||||||
|
index: 84
|
||||||
encoding: 0b1001000000000010
|
encoding: 0b1001000000000010
|
||||||
mask: 0b1111111111111111
|
mask: 0b1111111111111111
|
||||||
attributes: [[name:no_cont]]
|
|
||||||
size: 16
|
size: 16
|
||||||
branch: false
|
branch: false
|
||||||
delay: 1
|
delay: 1
|
||||||
- CSWSP:
|
C__SWSP:
|
||||||
|
index: 85
|
||||||
encoding: 0b1100000000000010
|
encoding: 0b1100000000000010
|
||||||
mask: 0b1110000000000011
|
mask: 0b1110000000000011
|
||||||
size: 16
|
size: 16
|
||||||
branch: false
|
branch: false
|
||||||
delay: 1
|
delay: 1
|
||||||
- DII:
|
DII:
|
||||||
|
index: 86
|
||||||
encoding: 0b0000000000000000
|
encoding: 0b0000000000000000
|
||||||
mask: 0b1111111111111111
|
mask: 0b1111111111111111
|
||||||
attributes: [[name:no_cont]]
|
|
||||||
size: 16
|
size: 16
|
||||||
branch: false
|
branch: false
|
||||||
delay: 1
|
delay: 1
|
||||||
650
contrib/instr/TGC5C_slow.yaml
Normal file
650
contrib/instr/TGC5C_slow.yaml
Normal file
@@ -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
|
||||||
@@ -19,7 +19,7 @@ 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 \
|
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}
|
-DCODEGEN=OFF -DCMAKE_INSTALL_PREFIX=${TGFS_INSTALL_ROOT}
|
||||||
cmake --build build/PA --target install -j16
|
cmake --build build/PA --target install -j16
|
||||||
cd dbt-rise-tgc/contrib
|
cd dbt-rise-tgc/contrib/pa
|
||||||
# import the TGC core itself
|
# import the TGC core itself
|
||||||
pct tgc_import_tb.tcl
|
pct tgc_import_tb.tcl
|
||||||
```
|
```
|
||||||
@@ -37,7 +37,7 @@ 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 \
|
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}
|
-DCODEGEN=OFF -DCMAKE_INSTALL_PREFIX=${TGFS_INSTALL_ROOT}
|
||||||
cmake --build build/PA --target install -j16
|
cmake --build build/PA --target install -j16
|
||||||
cd dbt-rise-tgc/contrib
|
cd dbt-rise-tgc/contrib/pa
|
||||||
# import the TGC core itself
|
# import the TGC core itself
|
||||||
pct tgc_import_tb.tcl
|
pct tgc_import_tb.tcl
|
||||||
```
|
```
|
||||||
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB |
@@ -1,8 +1,8 @@
|
|||||||
import "ISA/RV32I.core_desc"
|
import "ISA/RVI.core_desc"
|
||||||
import "ISA/RVM.core_desc"
|
import "ISA/RVM.core_desc"
|
||||||
import "ISA/RVC.core_desc"
|
import "ISA/RVC.core_desc"
|
||||||
|
|
||||||
Core TGC_C provides RV32I, Zicsr, Zifencei, RV32M, RV32IC {
|
Core TGC5C provides RV32I, Zicsr, Zifencei, RV32M, RV32IC {
|
||||||
architectural_state {
|
architectural_state {
|
||||||
XLEN=32;
|
XLEN=32;
|
||||||
// definitions for the architecture wrapper
|
// definitions for the architecture wrapper
|
||||||
@@ -37,6 +37,7 @@ def getRegisterSizes(){
|
|||||||
return regs
|
return regs
|
||||||
}
|
}
|
||||||
%>
|
%>
|
||||||
|
// clang-format off
|
||||||
#include "${coreDef.name.toLowerCase()}.h"
|
#include "${coreDef.name.toLowerCase()}.h"
|
||||||
#include "util/ities.h"
|
#include "util/ities.h"
|
||||||
#include <util/logging.h>
|
#include <util/logging.h>
|
||||||
@@ -70,7 +71,7 @@ uint8_t *${coreDef.name.toLowerCase()}::get_regs_base_ptr() {
|
|||||||
return reinterpret_cast<uint8_t*>(®);
|
return reinterpret_cast<uint8_t*>(®);
|
||||||
}
|
}
|
||||||
|
|
||||||
${coreDef.name.toLowerCase()}::phys_addr_t ${coreDef.name.toLowerCase()}::virt2phys(const iss::addr_t &pc) {
|
${coreDef.name.toLowerCase()}::phys_addr_t ${coreDef.name.toLowerCase()}::virt2phys(const iss::addr_t &addr) {
|
||||||
return phys_addr_t(pc); // change logical address to physical address
|
return phys_addr_t(addr.access, addr.space, addr.val&traits<${coreDef.name.toLowerCase()}>::addr_mask);
|
||||||
}
|
}
|
||||||
|
// clang-format on
|
||||||
|
|||||||
@@ -55,12 +55,12 @@ def byteSize(int size){
|
|||||||
return 128;
|
return 128;
|
||||||
}
|
}
|
||||||
def getCString(def val){
|
def getCString(def val){
|
||||||
return val.toString()
|
return val.toString()+'ULL'
|
||||||
}
|
}
|
||||||
%>
|
%>
|
||||||
#ifndef _${coreDef.name.toUpperCase()}_H_
|
#ifndef _${coreDef.name.toUpperCase()}_H_
|
||||||
#define _${coreDef.name.toUpperCase()}_H_
|
#define _${coreDef.name.toUpperCase()}_H_
|
||||||
|
// clang-format off
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <iss/arch/traits.h>
|
#include <iss/arch/traits.h>
|
||||||
#include <iss/arch_if.h>
|
#include <iss/arch_if.h>
|
||||||
@@ -76,10 +76,10 @@ template <> struct traits<${coreDef.name.toLowerCase()}> {
|
|||||||
constexpr static char const* const core_type = "${coreDef.name}";
|
constexpr static char const* const core_type = "${coreDef.name}";
|
||||||
|
|
||||||
static constexpr std::array<const char*, ${registers.size}> reg_names{
|
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{
|
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(', ')}};
|
enum constants {${constants.collect{c -> c.name+"="+getCString(c.value)}.join(', ')}};
|
||||||
|
|
||||||
@@ -137,14 +137,6 @@ struct ${coreDef.name.toLowerCase()}: public arch_if {
|
|||||||
|
|
||||||
inline uint64_t stop_code() { 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 phys_addr_t virt2phys(const iss::addr_t& addr);
|
||||||
|
|
||||||
virtual iss::sync_type needed_sync() const { return iss::NO_SYNC; }
|
virtual iss::sync_type needed_sync() const { return iss::NO_SYNC; }
|
||||||
@@ -182,3 +174,4 @@ if(fcsr != null) {%>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* _${coreDef.name.toUpperCase()}_H_ */
|
#endif /* _${coreDef.name.toUpperCase()}_H_ */
|
||||||
|
// clang-format on
|
||||||
|
|||||||
@@ -1,86 +0,0 @@
|
|||||||
#include "${coreDef.name.toLowerCase()}.h"
|
|
||||||
#include <vector>
|
|
||||||
#include <array>
|
|
||||||
#include <cstdlib>
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
namespace iss {
|
|
||||||
namespace arch {
|
|
||||||
namespace {
|
|
||||||
// according to
|
|
||||||
// https://stackoverflow.com/questions/8871204/count-number-of-1s-in-binary-representation
|
|
||||||
#ifdef __GCC__
|
|
||||||
constexpr size_t bit_count(uint32_t u) { return __builtin_popcount(u); }
|
|
||||||
#elif __cplusplus < 201402L
|
|
||||||
constexpr size_t uCount(uint32_t u) { return u - ((u >> 1) & 033333333333) - ((u >> 2) & 011111111111); }
|
|
||||||
constexpr size_t bit_count(uint32_t u) { return ((uCount(u) + (uCount(u) >> 3)) & 030707070707) % 63; }
|
|
||||||
#else
|
|
||||||
constexpr size_t bit_count(uint32_t u) {
|
|
||||||
size_t uCount = u - ((u >> 1) & 033333333333) - ((u >> 2) & 011111111111);
|
|
||||||
return ((uCount + (uCount >> 3)) & 030707070707) % 63;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
using opcode_e = traits<${coreDef.name.toLowerCase()}>::opcode_e;
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* start opcode definitions
|
|
||||||
****************************************************************************/
|
|
||||||
struct instruction_desriptor {
|
|
||||||
size_t length;
|
|
||||||
uint32_t value;
|
|
||||||
uint32_t mask;
|
|
||||||
opcode_e op;
|
|
||||||
};
|
|
||||||
|
|
||||||
const std::array<instruction_desriptor, ${instructions.size}> instr_descr = {{
|
|
||||||
/* entries are: size, valid value, valid mask, function ptr */<%instructions.each{instr -> %>
|
|
||||||
{${instr.length}, ${instr.encoding}, ${instr.mask}, opcode_e::${instr.instruction.name}},<%}%>
|
|
||||||
}};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
struct instruction_decoder<${coreDef.name.toLowerCase()}> {
|
|
||||||
using opcode_e = traits<${coreDef.name.toLowerCase()}>::opcode_e;
|
|
||||||
using code_word_t=traits<${coreDef.name.toLowerCase()}>::code_word_t;
|
|
||||||
|
|
||||||
struct instruction_pattern {
|
|
||||||
uint32_t value;
|
|
||||||
uint32_t mask;
|
|
||||||
opcode_e id;
|
|
||||||
};
|
|
||||||
|
|
||||||
std::array<std::vector<instruction_pattern>, 4> qlut;
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
unsigned decode_instruction(T);
|
|
||||||
|
|
||||||
instruction_decoder() {
|
|
||||||
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);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<>
|
|
||||||
unsigned instruction_decoder<${coreDef.name.toLowerCase()}>::decode_instruction<traits<${coreDef.name.toLowerCase()}>::code_word_t>(traits<${coreDef.name.toLowerCase()}>::code_word_t instr){
|
|
||||||
auto res = std::find_if(std::begin(qlut[instr&0x3]), std::end(qlut[instr&0x3]), [instr](instruction_pattern const& e){
|
|
||||||
return !((instr&e.mask) ^ e.value );
|
|
||||||
});
|
|
||||||
return static_cast<unsigned>(res!=std::end(qlut[instr&0x3])? res->id : opcode_e::MAX_OPCODE);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
std::unique_ptr<instruction_decoder<${coreDef.name.toLowerCase()}>> traits<${coreDef.name.toLowerCase()}>::get_decoder(){
|
|
||||||
return std::make_unique<instruction_decoder<${coreDef.name.toLowerCase()}>>();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -8,9 +8,10 @@
|
|||||||
instrGroups[groupName]+=it;
|
instrGroups[groupName]+=it;
|
||||||
}
|
}
|
||||||
instrGroups
|
instrGroups
|
||||||
}%><%getInstructionGroups().each{name, instrList -> %>
|
}%><%int index = 0; getInstructionGroups().each{name, instrList -> %>
|
||||||
${name}: <% instrList.findAll{!it.instruction.name.startsWith("__")}.each { %>
|
${name}: <% instrList.each { %>
|
||||||
- ${it.instruction.name}:
|
${it.instruction.name}:
|
||||||
|
index: ${index++}
|
||||||
encoding: ${it.encoding}
|
encoding: ${it.encoding}
|
||||||
mask: ${it.mask}<%if(it.attributes.size) {%>
|
mask: ${it.mask}<%if(it.attributes.size) {%>
|
||||||
attributes: ${it.attributes}<%}%>
|
attributes: ${it.attributes}<%}%>
|
||||||
|
|||||||
131
gen_input/templates/CORENAME_sysc.cpp.gtl
Normal file
131
gen_input/templates/CORENAME_sysc.cpp.gtl
Normal file
@@ -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
|
||||||
281
gen_input/templates/asmjit/CORENAME.cpp.gtl
Normal file
281
gen_input/templates/asmjit/CORENAME.cpp.gtl
Normal file
@@ -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>
|
||||||
|
#include <fp_functions.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 "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
|
||||||
@@ -34,15 +34,19 @@ def nativeTypeSize(int size){
|
|||||||
if(size<=8) return 8; else if(size<=16) return 16; else if(size<=32) return 32; else return 64;
|
if(size<=8) return 8; else if(size<=16) return 16; else if(size<=32) return 32; else return 64;
|
||||||
}
|
}
|
||||||
%>
|
%>
|
||||||
|
// clang-format off
|
||||||
#include <iss/arch/${coreDef.name.toLowerCase()}.h>
|
#include <iss/arch/${coreDef.name.toLowerCase()}.h>
|
||||||
#include <iss/debugger/gdb_session.h>
|
#include <iss/debugger/gdb_session.h>
|
||||||
#include <iss/debugger/server.h>
|
#include <iss/debugger/server.h>
|
||||||
#include <iss/iss.h>
|
#include <iss/iss.h>
|
||||||
#include <iss/interp/vm_base.h>
|
#include <iss/interp/vm_base.h>
|
||||||
|
#include <vm/fp_functions.h>
|
||||||
#include <util/logging.h>
|
#include <util/logging.h>
|
||||||
#include <sstream>
|
|
||||||
#include <boost/coroutine2/all.hpp>
|
#include <boost/coroutine2/all.hpp>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <exception>
|
||||||
|
#include <vector>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
#ifndef FMT_HEADER_ONLY
|
#ifndef FMT_HEADER_ONLY
|
||||||
#define FMT_HEADER_ONLY
|
#define FMT_HEADER_ONLY
|
||||||
@@ -59,6 +63,10 @@ using namespace iss::arch;
|
|||||||
using namespace iss::debugger;
|
using namespace iss::debugger;
|
||||||
using namespace std::placeholders;
|
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> {
|
template <typename ARCH> class vm_impl : public iss::interp::vm_base<ARCH> {
|
||||||
public:
|
public:
|
||||||
using traits = arch::traits<ARCH>;
|
using traits = arch::traits<ARCH>;
|
||||||
@@ -91,30 +99,9 @@ protected:
|
|||||||
|
|
||||||
inline const char *name(size_t index){return index<traits::reg_aliases.size()?traits::reg_aliases[index]:"illegal";}
|
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;
|
virt_addr_t execute_inst(finish_cond_e cond, virt_addr_t start, uint64_t icount_limit) override;
|
||||||
|
|
||||||
// some compile time constants
|
// 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){
|
inline void raise(uint16_t trap_id, uint16_t cause){
|
||||||
auto trap_val = 0x80ULL << 24 | (cause << 16) | trap_id;
|
auto trap_val = 0x80ULL << 24 | (cause << 16) | trap_id;
|
||||||
@@ -158,30 +145,96 @@ private:
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* start opcode definitions
|
* start opcode definitions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
struct InstructionDesriptor {
|
struct instruction_descriptor {
|
||||||
size_t length;
|
size_t length;
|
||||||
uint32_t value;
|
uint32_t value;
|
||||||
uint32_t mask;
|
uint32_t mask;
|
||||||
typename arch::traits<ARCH>::opcode_e op;
|
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 -> %>
|
/* 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}},<%}%>
|
{${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){
|
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 ((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 (this->core.read(phys_pc, 2, data) != iss::Ok) return iss::Err;
|
||||||
// if ((data[0] & 0x3) == 0x3) // this is a 32bit instruction
|
// 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 {
|
// } 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;
|
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) {
|
template <typename CODE_WORD> void debug_fn(CODE_WORD insn) {
|
||||||
@@ -208,16 +261,11 @@ constexpr size_t bit_count(uint32_t u) {
|
|||||||
template <typename ARCH>
|
template <typename ARCH>
|
||||||
vm_impl<ARCH>::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id)
|
vm_impl<ARCH>::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id)
|
||||||
: vm_base<ARCH>(core, core_id, 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){
|
for(auto instr:instr_descr){
|
||||||
auto quadrant = instr.value & 0x3;
|
root->instrs.push_back(instr);
|
||||||
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);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
populate_decoding_tree(root);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool is_count_limit_enabled(finish_cond_e cond){
|
inline bool is_count_limit_enabled(finish_cond_e cond){
|
||||||
@@ -228,14 +276,6 @@ 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;
|
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>
|
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){
|
typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e cond, virt_addr_t start, uint64_t icount_limit){
|
||||||
auto pc=start;
|
auto pc=start;
|
||||||
@@ -257,10 +297,11 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
|||||||
} else {
|
} else {
|
||||||
if (is_jump_to_self_enabled(cond) &&
|
if (is_jump_to_self_enabled(cond) &&
|
||||||
(instr == 0x0000006f || (instr&0xffff)==0xa001)) throw simulation_stopped(0); // 'J 0' or 'C.J 0'
|
(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
|
// pre execution stuff
|
||||||
this->core.reg.last_branch = 0;
|
this->core.reg.last_branch = 0;
|
||||||
if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, static_cast<unsigned>(inst_id));
|
if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, static_cast<unsigned>(inst_id));
|
||||||
|
try{
|
||||||
switch(inst_id){<%instructions.eachWithIndex{instr, idx -> %>
|
switch(inst_id){<%instructions.eachWithIndex{instr, idx -> %>
|
||||||
case arch::traits<ARCH>::opcode_e::${instr.name}: {
|
case arch::traits<ARCH>::opcode_e::${instr.name}: {
|
||||||
<%instr.fields.eachLine{%>${it}
|
<%instr.fields.eachLine{%>${it}
|
||||||
@@ -276,13 +317,14 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
|||||||
*NEXT_PC = *PC + ${instr.length/8};
|
*NEXT_PC = *PC + ${instr.length/8};
|
||||||
// execute instruction<%instr.behavior.eachLine{%>
|
// execute instruction<%instr.behavior.eachLine{%>
|
||||||
${it}<%}%>
|
${it}<%}%>
|
||||||
TRAP_${instr.name}:break;
|
break;
|
||||||
}// @suppress("No break at end of case")<%}%>
|
}// @suppress("No break at end of case")<%}%>
|
||||||
default: {
|
default: {
|
||||||
*NEXT_PC = *PC + ((instr & 3) == 3 ? 4 : 2);
|
*NEXT_PC = *PC + ((instr & 3) == 3 ? 4 : 2);
|
||||||
raise(0, 2);
|
raise(0, 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}catch(memory_access_exception& e){}
|
||||||
// post execution stuff
|
// post execution stuff
|
||||||
process_spawn_blocks();
|
process_spawn_blocks();
|
||||||
if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, static_cast<unsigned>(inst_id));
|
if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, static_cast<unsigned>(inst_id));
|
||||||
@@ -304,7 +346,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
|||||||
return pc;
|
return pc;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
} // namespace ${coreDef.name.toLowerCase()}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
std::unique_ptr<vm_if> create<arch::${coreDef.name.toLowerCase()}>(arch::${coreDef.name.toLowerCase()} *core, unsigned short port, bool dump) {
|
std::unique_ptr<vm_if> create<arch::${coreDef.name.toLowerCase()}>(arch::${coreDef.name.toLowerCase()} *core, unsigned short port, bool dump) {
|
||||||
@@ -320,7 +362,7 @@ std::unique_ptr<vm_if> create<arch::${coreDef.name.toLowerCase()}>(arch::${coreD
|
|||||||
#include <iss/arch/riscv_hart_mu_p.h>
|
#include <iss/arch/riscv_hart_mu_p.h>
|
||||||
namespace iss {
|
namespace iss {
|
||||||
namespace {
|
namespace {
|
||||||
std::array<bool, 2> dummy = {
|
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>{
|
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* 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);
|
auto vm = new interp::${coreDef.name.toLowerCase()}::vm_impl<arch::${coreDef.name.toLowerCase()}>(*cpu, false);
|
||||||
@@ -336,8 +378,4 @@ std::array<bool, 2> dummy = {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
extern "C" {
|
// clang-format on
|
||||||
bool* get_${coreDef.name.toLowerCase()}_interp_creators() {
|
|
||||||
return iss::dummy.data();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -29,11 +29,10 @@
|
|||||||
* POSSIBILITY OF SUCH DAMAGE.
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
// clang-format off
|
||||||
|
#include <iss/arch/${coreDef.name.toLowerCase()}.h>
|
||||||
#include <iss/debugger/gdb_session.h>
|
#include <iss/debugger/gdb_session.h>
|
||||||
#include <iss/debugger/server.h>
|
#include <iss/debugger/server.h>
|
||||||
#include <iss/arch/${coreDef.name.toLowerCase()}.h>
|
|
||||||
#include <iss/arch/riscv_hart_m_p.h>
|
|
||||||
#include <iss/iss.h>
|
#include <iss/iss.h>
|
||||||
#include <iss/llvm/vm_base.h>
|
#include <iss/llvm/vm_base.h>
|
||||||
#include <util/logging.h>
|
#include <util/logging.h>
|
||||||
@@ -59,6 +58,7 @@ using namespace iss::debugger;
|
|||||||
|
|
||||||
template <typename ARCH> class vm_impl : public iss::llvm::vm_base<ARCH> {
|
template <typename ARCH> class vm_impl : public iss::llvm::vm_base<ARCH> {
|
||||||
public:
|
public:
|
||||||
|
using traits = arch::traits<ARCH>;
|
||||||
using super = typename iss::llvm::vm_base<ARCH>;
|
using super = typename iss::llvm::vm_base<ARCH>;
|
||||||
using virt_addr_t = typename super::virt_addr_t;
|
using virt_addr_t = typename super::virt_addr_t;
|
||||||
using phys_addr_t = typename super::phys_addr_t;
|
using phys_addr_t = typename super::phys_addr_t;
|
||||||
@@ -81,7 +81,7 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
using vm_base<ARCH>::get_reg_ptr;
|
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) {
|
template <typename T> inline ConstantInt *size(T type) {
|
||||||
return ConstantInt::get(getContext(), APInt(32, type->getType()->getScalarSizeInBits()));
|
return ConstantInt::get(getContext(), APInt(32, type->getType()->getScalarSizeInBits()));
|
||||||
@@ -89,7 +89,7 @@ protected:
|
|||||||
|
|
||||||
void setup_module(Module* m) override {
|
void setup_module(Module* m) override {
|
||||||
super::setup_module(m);
|
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) {
|
inline Value *gen_choose(Value *cond, Value *trueVal, Value *falseVal, unsigned size) {
|
||||||
@@ -111,116 +111,150 @@ protected:
|
|||||||
void gen_trap_check(BasicBlock *bb);
|
void gen_trap_check(BasicBlock *bb);
|
||||||
|
|
||||||
inline Value *gen_reg_load(unsigned i, unsigned level = 0) {
|
inline Value *gen_reg_load(unsigned i, unsigned level = 0) {
|
||||||
return this->builder.CreateLoad(get_reg_ptr(i), false);
|
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) {
|
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),
|
Value *next_pc_v = this->builder.CreateSExtOrTrunc(this->gen_const(traits::XLEN, pc.val),
|
||||||
this->get_type(traits<ARCH>::XLEN));
|
this->get_type(traits::XLEN));
|
||||||
this->builder.CreateStore(next_pc_v, get_reg_ptr(reg_num), true);
|
this->builder.CreateStore(next_pc_v, get_reg_ptr(reg_num), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// some compile time constants
|
// 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 this_class = vm_impl<ARCH>;
|
||||||
using compile_func = std::tuple<continuation_e, BasicBlock *> (this_class::*)(virt_addr_t &pc,
|
using compile_func = std::tuple<continuation_e, BasicBlock *> (this_class::*)(virt_addr_t &pc,
|
||||||
code_word_t instr,
|
code_word_t instr,
|
||||||
BasicBlock *bb);
|
BasicBlock *bb);
|
||||||
std::array<compile_func, LUT_SIZE> lut;
|
template<unsigned W, typename U, typename S = typename std::make_signed<U>::type>
|
||||||
|
inline S sext(U from) {
|
||||||
std::array<compile_func, LUT_SIZE_C> lut_00, lut_01, lut_10;
|
auto mask = (1ULL<<W) - 1;
|
||||||
std::array<compile_func, LUT_SIZE> lut_11;
|
auto sign_mask = 1ULL<<(W-1);
|
||||||
|
return (from & mask) | ((from & sign_mask) ? ~mask : 0);
|
||||||
std::array<compile_func *, 4> qlut;
|
|
||||||
|
|
||||||
std::array<const uint32_t, 4> lutmasks = {{EXTR_MASK16, EXTR_MASK16, EXTR_MASK16, EXTR_MASK32}};
|
|
||||||
|
|
||||||
void expand_bit_mask(int pos, uint32_t mask, uint32_t value, uint32_t valid, uint32_t idx, compile_func lut[],
|
|
||||||
compile_func f) {
|
|
||||||
if (pos < 0) {
|
|
||||||
lut[idx] = f;
|
|
||||||
} else {
|
|
||||||
auto bitmask = 1UL << pos;
|
|
||||||
if ((mask & bitmask) == 0) {
|
|
||||||
expand_bit_mask(pos - 1, mask, value, valid, idx, lut, f);
|
|
||||||
} else {
|
|
||||||
if ((valid & bitmask) == 0) {
|
|
||||||
expand_bit_mask(pos - 1, mask, value, valid, (idx << 1), lut, f);
|
|
||||||
expand_bit_mask(pos - 1, mask, value, valid, (idx << 1) + 1, lut, f);
|
|
||||||
} else {
|
|
||||||
auto new_val = idx << 1;
|
|
||||||
if ((value & bitmask) != 0) new_val++;
|
|
||||||
expand_bit_mask(pos - 1, mask, value, valid, new_val, lut, f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline uint32_t extract_fields(uint32_t val) { return extract_fields(29, val >> 2, lutmasks[val & 0x3], 0); }
|
|
||||||
|
|
||||||
uint32_t extract_fields(int pos, uint32_t val, uint32_t mask, uint32_t lut_val) {
|
|
||||||
if (pos >= 0) {
|
|
||||||
auto bitmask = 1UL << pos;
|
|
||||||
if ((mask & bitmask) == 0) {
|
|
||||||
lut_val = extract_fields(pos - 1, val, mask, lut_val);
|
|
||||||
} else {
|
|
||||||
auto new_val = lut_val << 1;
|
|
||||||
if ((val & bitmask) != 0) new_val++;
|
|
||||||
lut_val = extract_fields(pos - 1, val, mask, new_val);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return lut_val;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* start opcode definitions
|
* start opcode definitions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
struct InstructionDesriptor {
|
struct instruction_descriptor {
|
||||||
size_t length;
|
size_t length;
|
||||||
uint32_t value;
|
uint32_t value;
|
||||||
uint32_t mask;
|
uint32_t mask;
|
||||||
compile_func op;
|
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 -> %>
|
/* entries are: size, valid value, valid mask, function ptr */<%instructions.each{instr -> %>
|
||||||
/* instruction ${instr.instruction.name} */
|
/* instruction ${instr.instruction.name}, encoding '${instr.encoding}' */
|
||||||
{${instr.length}, ${instr.value}, ${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 definitions */<%instructions.eachWithIndex{instr, idx -> %>
|
||||||
/* instruction ${idx}: ${instr.name} */
|
/* 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}<%}%>
|
${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
|
* end opcode definitions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
std::tuple<continuation_e, BasicBlock *> illegal_intruction(virt_addr_t &pc, code_word_t instr, BasicBlock *bb) {
|
std::tuple<continuation_e, BasicBlock *> illegal_intruction(virt_addr_t &pc, code_word_t instr, BasicBlock *bb) {
|
||||||
this->gen_sync(iss::PRE_SYNC, instr_descr.size());
|
this->gen_sync(iss::PRE_SYNC, instr_descr.size());
|
||||||
this->builder.CreateStore(this->builder.CreateLoad(get_reg_ptr(traits<ARCH>::NEXT_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<ARCH>::PC), true);
|
get_reg_ptr(traits::PC), true);
|
||||||
this->builder.CreateStore(
|
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)),
|
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);
|
pc = pc + ((instr & 3) == 3 ? 4 : 2);
|
||||||
this->gen_raise_trap(0, 2); // illegal instruction trap
|
this->gen_raise_trap(0, 2); // illegal instruction trap
|
||||||
this->gen_sync(iss::POST_SYNC, instr_descr.size());
|
this->gen_sync(iss::POST_SYNC, instr_descr.size());
|
||||||
this->gen_trap_check(this->leave_blk);
|
this->gen_trap_check(this->leave_blk);
|
||||||
return std::make_tuple(BRANCH, nullptr);
|
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) {
|
template <typename CODE_WORD> void debug_fn(CODE_WORD instr) {
|
||||||
volatile CODE_WORD x = insn;
|
volatile CODE_WORD x = instr;
|
||||||
insn = 2 * x;
|
instr = 2 * x;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename ARCH> vm_impl<ARCH>::vm_impl() { this(new ARCH()); }
|
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>
|
template <typename ARCH>
|
||||||
vm_impl<ARCH>::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id)
|
vm_impl<ARCH>::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id)
|
||||||
: vm_base<ARCH>(core, core_id, cluster_id) {
|
: vm_base<ARCH>(core, core_id, cluster_id) {
|
||||||
qlut[0] = lut_00.data();
|
root = new decoding_tree_node(std::numeric_limits<uint32_t>::max());
|
||||||
qlut[1] = lut_01.data();
|
|
||||||
qlut[2] = lut_10.data();
|
|
||||||
qlut[3] = lut_11.data();
|
|
||||||
for(auto instr:instr_descr){
|
for(auto instr:instr_descr){
|
||||||
auto quantrant = instr.value & 0x3;
|
root->instrs.push_back(instr);
|
||||||
expand_bit_mask(29, lutmasks[quantrant], instr.value >> 2, instr.mask >> 2, 0, qlut[quantrant], instr.op);
|
|
||||||
}
|
}
|
||||||
|
populate_decoding_tree(root);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename ARCH>
|
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) {
|
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
|
// we fetch at max 4 byte, alignment is 2
|
||||||
enum {TRAP_ID=1<<16};
|
enum {TRAP_ID=1<<16};
|
||||||
code_word_t insn = 0;
|
code_word_t instr = 0;
|
||||||
const typename traits<ARCH>::addr_t upper_bits = ~traits<ARCH>::PGMASK;
|
// const typename traits::addr_t upper_bits = ~traits::PGMASK;
|
||||||
phys_addr_t paddr(pc);
|
phys_addr_t paddr(pc);
|
||||||
auto *const data = (uint8_t *)&insn;
|
auto *const data = (uint8_t *)&instr;
|
||||||
paddr = this->core.v2p(pc);
|
if(this->core.has_mmu())
|
||||||
if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary
|
paddr = this->core.virt2phys(pc);
|
||||||
auto res = this->core.read(paddr, 2, data);
|
//TODO: re-add page handling
|
||||||
if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val);
|
// if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary
|
||||||
if ((insn & 0x3) == 0x3) { // this is a 32bit instruction
|
// auto res = this->core.read(paddr, 2, data);
|
||||||
res = this->core.read(this->core.v2p(pc + 2), 2, data + 2);
|
// if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val);
|
||||||
}
|
// if ((instr & 0x3) == 0x3) { // this is a 32bit instruction
|
||||||
} else {
|
// res = this->core.read(this->core.v2p(pc + 2), 2, data + 2);
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
auto res = this->core.read(paddr, 4, data);
|
auto res = this->core.read(paddr, 4, data);
|
||||||
if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val);
|
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
|
// curr pc on stack
|
||||||
++inst_cnt;
|
++inst_cnt;
|
||||||
auto lut_val = extract_fields(insn);
|
auto f = decode_instr(root, instr);
|
||||||
auto f = qlut[insn & 0x3][lut_val];
|
|
||||||
if (f == nullptr) {
|
if (f == nullptr) {
|
||||||
f = &this_class::illegal_intruction;
|
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) {
|
template <typename ARCH> void vm_impl<ARCH>::gen_leave_behavior(BasicBlock *leave_blk) {
|
||||||
this->builder.SetInsertPoint(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) {
|
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);
|
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(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<ARCH>::LAST_BRANCH), 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_leave_trap(unsigned lvl) {
|
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)) };
|
std::vector<Value *> args{ this->core_ptr, ConstantInt::get(getContext(), APInt(64, lvl)) };
|
||||||
this->builder.CreateCall(this->mod->getFunction("leave_trap"), args);
|
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);
|
auto *PC_val = this->gen_read_mem(traits::CSR, (lvl << 8) + 0x41, traits::XLEN / 8);
|
||||||
this->builder.CreateStore(PC_val, get_reg_ptr(traits<ARCH>::NEXT_PC), false);
|
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<ARCH>::LAST_BRANCH), 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) {
|
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) {
|
template <typename ARCH> void vm_impl<ARCH>::gen_trap_behavior(BasicBlock *trap_blk) {
|
||||||
this->builder.SetInsertPoint(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()),
|
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),
|
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);
|
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);
|
this->builder.CreateRet(trap_addr_val);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename ARCH> inline void vm_impl<ARCH>::gen_trap_check(BasicBlock *bb) {
|
template <typename ARCH> inline void vm_impl<ARCH>::gen_trap_check(BasicBlock *bb) {
|
||||||
auto *v = this->builder.CreateLoad(get_reg_ptr(arch::traits<ARCH>::TRAP_STATE), true);
|
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(
|
this->gen_cond_branch(this->builder.CreateICmp(
|
||||||
ICmpInst::ICMP_EQ, v,
|
ICmpInst::ICMP_EQ, v,
|
||||||
ConstantInt::get(getContext(), APInt(v->getType()->getIntegerBitWidth(), 0))),
|
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()}
|
} // namespace ${coreDef.name.toLowerCase()}
|
||||||
@@ -323,3 +358,26 @@ std::unique_ptr<vm_if> create<arch::${coreDef.name.toLowerCase()}>(arch::${coreD
|
|||||||
}
|
}
|
||||||
} // namespace llvm
|
} // namespace llvm
|
||||||
} // namespace iss
|
} // 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,7 +29,7 @@
|
|||||||
* POSSIBILITY OF SUCH DAMAGE.
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
// clang-format off
|
||||||
#include <iss/arch/${coreDef.name.toLowerCase()}.h>
|
#include <iss/arch/${coreDef.name.toLowerCase()}.h>
|
||||||
#include <iss/debugger/gdb_session.h>
|
#include <iss/debugger/gdb_session.h>
|
||||||
#include <iss/debugger/server.h>
|
#include <iss/debugger/server.h>
|
||||||
@@ -120,57 +120,7 @@ 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(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;
|
|
||||||
|
|
||||||
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>
|
template<unsigned W, typename U, typename S = typename std::make_signed<U>::type>
|
||||||
inline S sext(U from) {
|
inline S sext(U from) {
|
||||||
auto mask = (1ULL<<W) - 1;
|
auto mask = (1ULL<<W) - 1;
|
||||||
@@ -182,14 +132,23 @@ private:
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* start opcode definitions
|
* start opcode definitions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
struct InstructionDesriptor {
|
struct instruction_descriptor {
|
||||||
size_t length;
|
size_t length;
|
||||||
uint32_t value;
|
uint32_t value;
|
||||||
uint32_t mask;
|
uint32_t mask;
|
||||||
compile_func op;
|
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 -> %>
|
/* entries are: size, valid value, valid mask, function ptr */<%instructions.each{instr -> %>
|
||||||
/* instruction ${instr.instruction.name}, encoding '${instr.encoding}' */
|
/* instruction ${instr.instruction.name}, encoding '${instr.encoding}' */
|
||||||
{${instr.length}, ${instr.encoding}, ${instr.mask}, &this_class::__${generator.functionName(instr.name)}},<%}%>
|
{${instr.length}, ${instr.encoding}, ${instr.mask}, &this_class::__${generator.functionName(instr.name)}},<%}%>
|
||||||
@@ -200,6 +159,7 @@ private:
|
|||||||
compile_ret_t __${generator.functionName(instr.name)}(virt_addr_t& pc, code_word_t instr, tu_builder& tu){
|
compile_ret_t __${generator.functionName(instr.name)}(virt_addr_t& pc, code_word_t instr, tu_builder& tu){
|
||||||
tu("${instr.name}_{:#010x}:", pc.val);
|
tu("${instr.name}_{:#010x}:", pc.val);
|
||||||
vm_base<ARCH>::gen_sync(tu, PRE_SYNC,${idx});
|
vm_base<ARCH>::gen_sync(tu, PRE_SYNC,${idx});
|
||||||
|
uint64_t PC = pc.val;
|
||||||
<%instr.fields.eachLine{%>${it}
|
<%instr.fields.eachLine{%>${it}
|
||||||
<%}%>if(this->disass_enabled){
|
<%}%>if(this->disass_enabled){
|
||||||
/* generate console output when executing the command */<%instr.disass.eachLine{%>
|
/* generate console output when executing the command */<%instr.disass.eachLine{%>
|
||||||
@@ -208,11 +168,12 @@ private:
|
|||||||
auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]);
|
auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]);
|
||||||
pc=pc+ ${instr.length/8};
|
pc=pc+ ${instr.length/8};
|
||||||
gen_set_pc(tu, pc, traits::NEXT_PC);
|
gen_set_pc(tu, pc, traits::NEXT_PC);
|
||||||
tu.open_scope();<%instr.behavior.eachLine{%>
|
tu.open_scope();
|
||||||
${it}<%}%>
|
<%instr.behavior.eachLine{%>${it}
|
||||||
|
<%}%>
|
||||||
tu.close_scope();
|
tu.close_scope();
|
||||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,${idx});
|
|
||||||
gen_trap_check(tu);
|
gen_trap_check(tu);
|
||||||
|
vm_base<ARCH>::gen_sync(tu, POST_SYNC,${idx});
|
||||||
return returnValue;
|
return returnValue;
|
||||||
}
|
}
|
||||||
<%}%>
|
<%}%>
|
||||||
@@ -227,11 +188,64 @@ private:
|
|||||||
vm_impl::gen_trap_check(tu);
|
vm_impl::gen_trap_check(tu);
|
||||||
return BRANCH;
|
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) {
|
template <typename CODE_WORD> void debug_fn(CODE_WORD instr) {
|
||||||
volatile CODE_WORD x = insn;
|
volatile CODE_WORD x = instr;
|
||||||
insn = 2 * x;
|
instr = 2 * x;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename ARCH> vm_impl<ARCH>::vm_impl() { this(new ARCH()); }
|
template <typename ARCH> vm_impl<ARCH>::vm_impl() { this(new ARCH()); }
|
||||||
@@ -239,14 +253,11 @@ template <typename ARCH> vm_impl<ARCH>::vm_impl() { this(new ARCH()); }
|
|||||||
template <typename ARCH>
|
template <typename ARCH>
|
||||||
vm_impl<ARCH>::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id)
|
vm_impl<ARCH>::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id)
|
||||||
: vm_base<ARCH>(core, core_id, cluster_id) {
|
: vm_base<ARCH>(core, core_id, cluster_id) {
|
||||||
qlut[0] = lut_00.data();
|
root = new decoding_tree_node(std::numeric_limits<uint32_t>::max());
|
||||||
qlut[1] = lut_01.data();
|
|
||||||
qlut[2] = lut_10.data();
|
|
||||||
qlut[3] = lut_11.data();
|
|
||||||
for(auto instr:instr_descr){
|
for(auto instr:instr_descr){
|
||||||
auto quantrant = instr.value & 0x3;
|
root->instrs.push_back(instr);
|
||||||
expand_bit_mask(29, lutmasks[quantrant], instr.value >> 2, instr.mask >> 2, 0, qlut[quantrant], instr.op);
|
|
||||||
}
|
}
|
||||||
|
populate_decoding_tree(root);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename ARCH>
|
template <typename ARCH>
|
||||||
@@ -254,11 +265,11 @@ std::tuple<continuation_e>
|
|||||||
vm_impl<ARCH>::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, tu_builder& tu) {
|
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
|
// we fetch at max 4 byte, alignment is 2
|
||||||
enum {TRAP_ID=1<<16};
|
enum {TRAP_ID=1<<16};
|
||||||
code_word_t insn = 0;
|
code_word_t instr = 0;
|
||||||
// const typename traits::addr_t upper_bits = ~traits::PGMASK;
|
|
||||||
phys_addr_t paddr(pc);
|
phys_addr_t paddr(pc);
|
||||||
auto *const data = (uint8_t *)&insn;
|
if(this->core.has_mmu())
|
||||||
paddr = this->core.v2p(pc);
|
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
|
// if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary
|
||||||
// auto res = this->core.read(paddr, 2, data);
|
// auto res = this->core.read(paddr, 2, data);
|
||||||
// if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val);
|
// if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val);
|
||||||
@@ -266,18 +277,17 @@ vm_impl<ARCH>::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt,
|
|||||||
// res = this->core.read(this->core.v2p(pc + 2), 2, data + 2);
|
// res = this->core.read(this->core.v2p(pc + 2), 2, data + 2);
|
||||||
// }
|
// }
|
||||||
// } else {
|
// } else {
|
||||||
auto res = this->core.read(paddr, 4, data);
|
auto res = this->core.read(paddr, 4, reinterpret_cast<uint8_t*>(&instr));
|
||||||
if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val);
|
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
|
// curr pc on stack
|
||||||
++inst_cnt;
|
++inst_cnt;
|
||||||
auto lut_val = extract_fields(insn);
|
auto f = decode_instr(root, instr);
|
||||||
auto f = qlut[insn & 0x3][lut_val];
|
|
||||||
if (f == nullptr) {
|
if (f == nullptr) {
|
||||||
f = &this_class::illegal_intruction;
|
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) {
|
template <typename ARCH> void vm_impl<ARCH>::gen_raise_trap(tu_builder& tu, uint16_t trap_id, uint16_t cause) {
|
||||||
@@ -296,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) {
|
template <typename ARCH> void vm_impl<ARCH>::gen_trap_behavior(tu_builder& tu) {
|
||||||
tu("trap_entry:");
|
tu("trap_entry:");
|
||||||
|
this->gen_sync(tu, POST_SYNC, -1);
|
||||||
tu("enter_trap(core_ptr, *trap_state, *pc, 0);");
|
tu("enter_trap(core_ptr, *trap_state, *pc, 0);");
|
||||||
tu.store(traits::LAST_BRANCH, tu.constant(std::numeric_limits<uint32_t>::max(),32));
|
tu.store(traits::LAST_BRANCH, tu.constant(std::numeric_limits<uint32_t>::max(),32));
|
||||||
tu("return *next_pc;");
|
tu("return *next_pc;");
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace mnrv32
|
} // namespace ${coreDef.name.toLowerCase()}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
std::unique_ptr<vm_if> create<arch::${coreDef.name.toLowerCase()}>(arch::${coreDef.name.toLowerCase()} *core, unsigned short port, bool dump) {
|
std::unique_ptr<vm_if> create<arch::${coreDef.name.toLowerCase()}>(arch::${coreDef.name.toLowerCase()} *core, unsigned short port, bool dump) {
|
||||||
@@ -317,7 +328,7 @@ std::unique_ptr<vm_if> create<arch::${coreDef.name.toLowerCase()}>(arch::${coreD
|
|||||||
#include <iss/arch/riscv_hart_mu_p.h>
|
#include <iss/arch/riscv_hart_mu_p.h>
|
||||||
namespace iss {
|
namespace iss {
|
||||||
namespace {
|
namespace {
|
||||||
std::array<bool, 2> dummy = {
|
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>{
|
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* 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);
|
auto vm = new tcc::${coreDef.name.toLowerCase()}::vm_impl<arch::${coreDef.name.toLowerCase()}>(*cpu, false);
|
||||||
@@ -333,8 +344,4 @@ std::array<bool, 2> dummy = {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
extern "C" {
|
// clang-format on
|
||||||
bool* get_${coreDef.name.toLowerCase()}_tcc_creators() {
|
|
||||||
return iss::dummy.data();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -50,4 +50,3 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
#define SOFTFLOAT_BUILTIN_CLZ 1
|
#define SOFTFLOAT_BUILTIN_CLZ 1
|
||||||
#include "opts-GCC.h"
|
#include "opts-GCC.h"
|
||||||
|
|
||||||
|
|||||||
@@ -50,4 +50,3 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
#define SOFTFLOAT_BUILTIN_CLZ 1
|
#define SOFTFLOAT_BUILTIN_CLZ 1
|
||||||
#include "opts-GCC.h"
|
#include "opts-GCC.h"
|
||||||
|
|
||||||
|
|||||||
@@ -50,4 +50,3 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
#define SOFTFLOAT_BUILTIN_CLZ 1
|
#define SOFTFLOAT_BUILTIN_CLZ 1
|
||||||
#include "opts-GCC.h"
|
#include "opts-GCC.h"
|
||||||
|
|
||||||
|
|||||||
@@ -54,4 +54,3 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#define SOFTFLOAT_INTRINSIC_INT128 1
|
#define SOFTFLOAT_INTRINSIC_INT128 1
|
||||||
#endif
|
#endif
|
||||||
#include "opts-GCC.h"
|
#include "opts-GCC.h"
|
||||||
|
|
||||||
|
|||||||
@@ -50,4 +50,3 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
#define SOFTFLOAT_BUILTIN_CLZ 1
|
#define SOFTFLOAT_BUILTIN_CLZ 1
|
||||||
#include "opts-GCC.h"
|
#include "opts-GCC.h"
|
||||||
|
|
||||||
|
|||||||
@@ -50,4 +50,3 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
#define SOFTFLOAT_BUILTIN_CLZ 1
|
#define SOFTFLOAT_BUILTIN_CLZ 1
|
||||||
#include "opts-GCC.h"
|
#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_BUILTIN_CLZ 1
|
||||||
#define SOFTFLOAT_INTRINSIC_INT128 1
|
#define SOFTFLOAT_INTRINSIC_INT128 1
|
||||||
#include "opts-GCC.h"
|
#include "opts-GCC.h"
|
||||||
|
|
||||||
|
|||||||
@@ -47,4 +47,3 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
== > #define THREAD_LOCAL _Thread_local
|
== > #define THREAD_LOCAL _Thread_local
|
||||||
|
|
||||||
|
|||||||
@@ -47,4 +47,3 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
== > #define THREAD_LOCAL _Thread_local
|
== > #define THREAD_LOCAL _Thread_local
|
||||||
|
|
||||||
|
|||||||
@@ -37,10 +37,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#ifndef specialize_h
|
#ifndef specialize_h
|
||||||
#define specialize_h 1
|
#define specialize_h 1
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include "primitiveTypes.h"
|
#include "primitiveTypes.h"
|
||||||
#include "softfloat.h"
|
#include "softfloat.h"
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
| Default value for 'softfloat_detectTininess'.
|
| 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
|
| the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a
|
||||||
| signaling NaN, the invalid exception is raised.
|
| signaling NaN, the invalid exception is raised.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
uint_fast16_t
|
uint_fast16_t softfloat_propagateNaNF16UI(uint_fast16_t uiA, uint_fast16_t uiB);
|
||||||
softfloat_propagateNaNF16UI( uint_fast16_t uiA, uint_fast16_t uiB );
|
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
| The bit pattern for a default generated 32-bit floating-point NaN.
|
| 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
|
| the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a
|
||||||
| signaling NaN, the invalid exception is raised.
|
| signaling NaN, the invalid exception is raised.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
uint_fast32_t
|
uint_fast32_t softfloat_propagateNaNF32UI(uint_fast32_t uiA, uint_fast32_t uiB);
|
||||||
softfloat_propagateNaNF32UI( uint_fast32_t uiA, uint_fast32_t uiB );
|
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
| The bit pattern for a default generated 64-bit floating-point NaN.
|
| 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.
|
| 64-bit floating-point signaling NaN.
|
||||||
| Note: This macro evaluates its argument more than once.
|
| 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
|
| 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
|
| the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a
|
||||||
| signaling NaN, the invalid exception is raised.
|
| signaling NaN, the invalid exception is raised.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
uint_fast64_t
|
uint_fast64_t softfloat_propagateNaNF64UI(uint_fast64_t uiA, uint_fast64_t uiB);
|
||||||
softfloat_propagateNaNF64UI( uint_fast64_t uiA, uint_fast64_t uiB );
|
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
| The bit pattern for a default generated 80-bit extended floating-point NaN.
|
| The bit pattern for a default generated 80-bit extended floating-point NaN.
|
||||||
@@ -199,7 +197,8 @@ uint_fast64_t
|
|||||||
| floating-point signaling NaN.
|
| floating-point signaling NaN.
|
||||||
| Note: This macro evaluates its arguments more than once.
|
| 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
|
#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
|
| location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid
|
||||||
| exception is raised.
|
| exception is raised.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
void
|
void softfloat_extF80UIToCommonNaN(uint_fast16_t uiA64, uint_fast64_t uiA0, struct commonNaN* zPtr);
|
||||||
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
|
| 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
|
| result. If either original floating-point value is a signaling NaN, the
|
||||||
| invalid exception is raised.
|
| invalid exception is raised.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
struct uint128
|
struct uint128 softfloat_propagateNaNExtF80UI(uint_fast16_t uiA64, uint_fast64_t uiA0, uint_fast16_t uiB64, uint_fast64_t uiB0);
|
||||||
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.
|
| The bit pattern for a default generated 128-bit floating-point NaN.
|
||||||
@@ -255,7 +246,8 @@ struct uint128
|
|||||||
| point signaling NaN.
|
| point signaling NaN.
|
||||||
| Note: This macro evaluates its arguments more than once.
|
| 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'
|
| 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
|
| pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid exception
|
||||||
| is raised.
|
| is raised.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
void
|
void softfloat_f128UIToCommonNaN(uint_fast64_t uiA64, uint_fast64_t uiA0, struct commonNaN* zPtr);
|
||||||
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
|
| 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
|
| If either original floating-point value is a signaling NaN, the invalid
|
||||||
| exception is raised.
|
| exception is raised.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
struct uint128
|
struct uint128 softfloat_propagateNaNF128UI(uint_fast64_t uiA64, uint_fast64_t uiA0, uint_fast64_t uiB64, uint_fast64_t uiB0);
|
||||||
softfloat_propagateNaNF128UI(
|
|
||||||
uint_fast64_t uiA64,
|
|
||||||
uint_fast64_t uiA0,
|
|
||||||
uint_fast64_t uiB64,
|
|
||||||
uint_fast64_t uiB0
|
|
||||||
);
|
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
@@ -304,18 +288,14 @@ struct uint128
|
|||||||
| common NaN at the location pointed to by 'zPtr'. If the NaN is a signaling
|
| common NaN at the location pointed to by 'zPtr'. If the NaN is a signaling
|
||||||
| NaN, the invalid exception is raised.
|
| NaN, the invalid exception is raised.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
void
|
void softfloat_extF80MToCommonNaN(const struct extFloat80M* aSPtr, struct commonNaN* zPtr);
|
||||||
softfloat_extF80MToCommonNaN(
|
|
||||||
const struct extFloat80M *aSPtr, struct commonNaN *zPtr );
|
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
| Converts the common NaN pointed to by 'aPtr' into an 80-bit extended
|
| 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
|
| floating-point NaN, and stores this NaN at the location pointed to by
|
||||||
| 'zSPtr'.
|
| 'zSPtr'.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
void
|
void softfloat_commonNaNToExtF80M(const struct commonNaN* aPtr, struct extFloat80M* zSPtr);
|
||||||
softfloat_commonNaNToExtF80M(
|
|
||||||
const struct commonNaN *aPtr, struct extFloat80M *zSPtr );
|
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
| Assuming at least one of the two 80-bit extended floating-point values
|
| 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
|
| at the location pointed to by 'zSPtr'. If either original floating-point
|
||||||
| value is a signaling NaN, the invalid exception is raised.
|
| value is a signaling NaN, the invalid exception is raised.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
void
|
void softfloat_propagateNaNExtF80M(const struct extFloat80M* aSPtr, const struct extFloat80M* bSPtr, struct extFloat80M* zSPtr);
|
||||||
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.
|
| 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
|
| four 32-bit elements that concatenate in the platform's normal endian order
|
||||||
| to form a 128-bit floating-point value.
|
| to form a 128-bit floating-point value.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
void
|
void softfloat_f128MToCommonNaN(const uint32_t* aWPtr, struct commonNaN* zPtr);
|
||||||
softfloat_f128MToCommonNaN( const uint32_t *aWPtr, struct commonNaN *zPtr );
|
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
| Converts the common NaN pointed to by 'aPtr' into a 128-bit floating-point
|
| 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
|
| '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.
|
| platform's normal endian order to form a 128-bit floating-point value.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
void
|
void softfloat_commonNaNToF128M(const struct commonNaN* aPtr, uint32_t* zWPtr);
|
||||||
softfloat_commonNaNToF128M( const struct commonNaN *aPtr, uint32_t *zWPtr );
|
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
| Assuming at least one of the two 128-bit floating-point values pointed to by
|
| 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
|
| 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.
|
| the platform's normal endian order to form a 128-bit floating-point value.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
void
|
void softfloat_propagateNaNF128M(const uint32_t* aWPtr, const uint32_t* bWPtr, uint32_t* zWPtr);
|
||||||
softfloat_propagateNaNF128M(
|
|
||||||
const uint32_t *aWPtr, const uint32_t *bWPtr, uint32_t *zWPtr );
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -37,10 +37,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#ifndef specialize_h
|
#ifndef specialize_h
|
||||||
#define specialize_h 1
|
#define specialize_h 1
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include "primitiveTypes.h"
|
#include "primitiveTypes.h"
|
||||||
#include "softfloat.h"
|
#include "softfloat.h"
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
| Default value for 'softfloat_detectTininess'.
|
| 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
|
| the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a
|
||||||
| signaling NaN, the invalid exception is raised.
|
| signaling NaN, the invalid exception is raised.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
uint_fast16_t
|
uint_fast16_t softfloat_propagateNaNF16UI(uint_fast16_t uiA, uint_fast16_t uiB);
|
||||||
softfloat_propagateNaNF16UI( uint_fast16_t uiA, uint_fast16_t uiB );
|
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
| The bit pattern for a default generated 32-bit floating-point NaN.
|
| 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
|
| the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a
|
||||||
| signaling NaN, the invalid exception is raised.
|
| signaling NaN, the invalid exception is raised.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
uint_fast32_t
|
uint_fast32_t softfloat_propagateNaNF32UI(uint_fast32_t uiA, uint_fast32_t uiB);
|
||||||
softfloat_propagateNaNF32UI( uint_fast32_t uiA, uint_fast32_t uiB );
|
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
| The bit pattern for a default generated 64-bit floating-point NaN.
|
| 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.
|
| 64-bit floating-point signaling NaN.
|
||||||
| Note: This macro evaluates its argument more than once.
|
| 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
|
| 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
|
| the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a
|
||||||
| signaling NaN, the invalid exception is raised.
|
| signaling NaN, the invalid exception is raised.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
uint_fast64_t
|
uint_fast64_t softfloat_propagateNaNF64UI(uint_fast64_t uiA, uint_fast64_t uiB);
|
||||||
softfloat_propagateNaNF64UI( uint_fast64_t uiA, uint_fast64_t uiB );
|
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
| The bit pattern for a default generated 80-bit extended floating-point NaN.
|
| The bit pattern for a default generated 80-bit extended floating-point NaN.
|
||||||
@@ -199,7 +197,8 @@ uint_fast64_t
|
|||||||
| floating-point signaling NaN.
|
| floating-point signaling NaN.
|
||||||
| Note: This macro evaluates its arguments more than once.
|
| 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
|
#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
|
| location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid
|
||||||
| exception is raised.
|
| exception is raised.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
void
|
void softfloat_extF80UIToCommonNaN(uint_fast16_t uiA64, uint_fast64_t uiA0, struct commonNaN* zPtr);
|
||||||
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
|
| 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
|
| result. If either original floating-point value is a signaling NaN, the
|
||||||
| invalid exception is raised.
|
| invalid exception is raised.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
struct uint128
|
struct uint128 softfloat_propagateNaNExtF80UI(uint_fast16_t uiA64, uint_fast64_t uiA0, uint_fast16_t uiB64, uint_fast64_t uiB0);
|
||||||
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.
|
| The bit pattern for a default generated 128-bit floating-point NaN.
|
||||||
@@ -255,7 +246,8 @@ struct uint128
|
|||||||
| point signaling NaN.
|
| point signaling NaN.
|
||||||
| Note: This macro evaluates its arguments more than once.
|
| 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'
|
| 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
|
| pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid exception
|
||||||
| is raised.
|
| is raised.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
void
|
void softfloat_f128UIToCommonNaN(uint_fast64_t uiA64, uint_fast64_t uiA0, struct commonNaN* zPtr);
|
||||||
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
|
| 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
|
| If either original floating-point value is a signaling NaN, the invalid
|
||||||
| exception is raised.
|
| exception is raised.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
struct uint128
|
struct uint128 softfloat_propagateNaNF128UI(uint_fast64_t uiA64, uint_fast64_t uiA0, uint_fast64_t uiB64, uint_fast64_t uiB0);
|
||||||
softfloat_propagateNaNF128UI(
|
|
||||||
uint_fast64_t uiA64,
|
|
||||||
uint_fast64_t uiA0,
|
|
||||||
uint_fast64_t uiB64,
|
|
||||||
uint_fast64_t uiB0
|
|
||||||
);
|
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
@@ -304,18 +288,14 @@ struct uint128
|
|||||||
| common NaN at the location pointed to by 'zPtr'. If the NaN is a signaling
|
| common NaN at the location pointed to by 'zPtr'. If the NaN is a signaling
|
||||||
| NaN, the invalid exception is raised.
|
| NaN, the invalid exception is raised.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
void
|
void softfloat_extF80MToCommonNaN(const struct extFloat80M* aSPtr, struct commonNaN* zPtr);
|
||||||
softfloat_extF80MToCommonNaN(
|
|
||||||
const struct extFloat80M *aSPtr, struct commonNaN *zPtr );
|
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
| Converts the common NaN pointed to by 'aPtr' into an 80-bit extended
|
| 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
|
| floating-point NaN, and stores this NaN at the location pointed to by
|
||||||
| 'zSPtr'.
|
| 'zSPtr'.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
void
|
void softfloat_commonNaNToExtF80M(const struct commonNaN* aPtr, struct extFloat80M* zSPtr);
|
||||||
softfloat_commonNaNToExtF80M(
|
|
||||||
const struct commonNaN *aPtr, struct extFloat80M *zSPtr );
|
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
| Assuming at least one of the two 80-bit extended floating-point values
|
| 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
|
| at the location pointed to by 'zSPtr'. If either original floating-point
|
||||||
| value is a signaling NaN, the invalid exception is raised.
|
| value is a signaling NaN, the invalid exception is raised.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
void
|
void softfloat_propagateNaNExtF80M(const struct extFloat80M* aSPtr, const struct extFloat80M* bSPtr, struct extFloat80M* zSPtr);
|
||||||
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.
|
| 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
|
| four 32-bit elements that concatenate in the platform's normal endian order
|
||||||
| to form a 128-bit floating-point value.
|
| to form a 128-bit floating-point value.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
void
|
void softfloat_f128MToCommonNaN(const uint32_t* aWPtr, struct commonNaN* zPtr);
|
||||||
softfloat_f128MToCommonNaN( const uint32_t *aWPtr, struct commonNaN *zPtr );
|
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
| Converts the common NaN pointed to by 'aPtr' into a 128-bit floating-point
|
| 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
|
| '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.
|
| platform's normal endian order to form a 128-bit floating-point value.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
void
|
void softfloat_commonNaNToF128M(const struct commonNaN* aPtr, uint32_t* zWPtr);
|
||||||
softfloat_commonNaNToF128M( const struct commonNaN *aPtr, uint32_t *zWPtr );
|
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
| Assuming at least one of the two 128-bit floating-point values pointed to by
|
| 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
|
| 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.
|
| the platform's normal endian order to form a 128-bit floating-point value.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
void
|
void softfloat_propagateNaNF128M(const uint32_t* aWPtr, const uint32_t* bWPtr, uint32_t* zWPtr);
|
||||||
softfloat_propagateNaNF128M(
|
|
||||||
const uint32_t *aWPtr, const uint32_t *bWPtr, uint32_t *zWPtr );
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -37,10 +37,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#ifndef specialize_h
|
#ifndef specialize_h
|
||||||
#define specialize_h 1
|
#define specialize_h 1
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include "primitiveTypes.h"
|
#include "primitiveTypes.h"
|
||||||
#include "softfloat.h"
|
#include "softfloat.h"
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
| Default value for 'softfloat_detectTininess'.
|
| 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
|
| "Common NaN" structure, used to transfer NaN representations from one format
|
||||||
| to another.
|
| to another.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
struct commonNaN { char _unused; };
|
struct commonNaN {
|
||||||
|
char _unused;
|
||||||
|
};
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
| The bit pattern for a default generated 16-bit floating-point NaN.
|
| 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
|
| location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid
|
||||||
| exception is raised.
|
| 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
|
| 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
|
| the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a
|
||||||
| signaling NaN, the invalid exception is raised.
|
| signaling NaN, the invalid exception is raised.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
uint_fast16_t
|
uint_fast16_t softfloat_propagateNaNF16UI(uint_fast16_t uiA, uint_fast16_t uiB);
|
||||||
softfloat_propagateNaNF16UI( uint_fast16_t uiA, uint_fast16_t uiB );
|
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
| The bit pattern for a default generated 32-bit floating-point NaN.
|
| 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
|
| location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid
|
||||||
| exception is raised.
|
| 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
|
| 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
|
| the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a
|
||||||
| signaling NaN, the invalid exception is raised.
|
| signaling NaN, the invalid exception is raised.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
uint_fast32_t
|
uint_fast32_t softfloat_propagateNaNF32UI(uint_fast32_t uiA, uint_fast32_t uiB);
|
||||||
softfloat_propagateNaNF32UI( uint_fast32_t uiA, uint_fast32_t uiB );
|
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
| The bit pattern for a default generated 64-bit floating-point NaN.
|
| 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.
|
| 64-bit floating-point signaling NaN.
|
||||||
| Note: This macro evaluates its argument more than once.
|
| 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
|
| 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
|
| location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid
|
||||||
| exception is raised.
|
| 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
|
| 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
|
| the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a
|
||||||
| signaling NaN, the invalid exception is raised.
|
| signaling NaN, the invalid exception is raised.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
uint_fast64_t
|
uint_fast64_t softfloat_propagateNaNF64UI(uint_fast64_t uiA, uint_fast64_t uiB);
|
||||||
softfloat_propagateNaNF64UI( uint_fast64_t uiA, uint_fast64_t uiB );
|
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
| The bit pattern for a default generated 80-bit extended floating-point NaN.
|
| The bit pattern for a default generated 80-bit extended floating-point NaN.
|
||||||
@@ -192,7 +198,8 @@ uint_fast64_t
|
|||||||
| floating-point signaling NaN.
|
| floating-point signaling NaN.
|
||||||
| Note: This macro evaluates its arguments more than once.
|
| 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
|
#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
|
| location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid
|
||||||
| exception is raised.
|
| 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
|
| 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
|
#if defined INLINE && !defined softfloat_commonNaNToExtF80UI
|
||||||
INLINE
|
INLINE
|
||||||
struct uint128 softfloat_commonNaNToExtF80UI( const struct commonNaN *aPtr )
|
struct uint128 softfloat_commonNaNToExtF80UI(const struct commonNaN* aPtr) {
|
||||||
{
|
|
||||||
struct uint128 uiZ;
|
struct uint128 uiZ;
|
||||||
uiZ.v64 = defaultNaNExtF80UI64;
|
uiZ.v64 = defaultNaNExtF80UI64;
|
||||||
uiZ.v0 = defaultNaNExtF80UI0;
|
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
|
| result. If either original floating-point value is a signaling NaN, the
|
||||||
| invalid exception is raised.
|
| invalid exception is raised.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
struct uint128
|
struct uint128 softfloat_propagateNaNExtF80UI(uint_fast16_t uiA64, uint_fast64_t uiA0, uint_fast16_t uiB64, uint_fast64_t uiB0);
|
||||||
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.
|
| The bit pattern for a default generated 128-bit floating-point NaN.
|
||||||
@@ -257,7 +259,8 @@ struct uint128
|
|||||||
| point signaling NaN.
|
| point signaling NaN.
|
||||||
| Note: This macro evaluates its arguments more than once.
|
| 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'
|
| 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
|
| pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid exception
|
||||||
| is raised.
|
| 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
|
| 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
|
#if defined INLINE && !defined softfloat_commonNaNToF128UI
|
||||||
INLINE
|
INLINE
|
||||||
struct uint128 softfloat_commonNaNToF128UI( const struct commonNaN *aPtr )
|
struct uint128 softfloat_commonNaNToF128UI(const struct commonNaN* aPtr) {
|
||||||
{
|
|
||||||
struct uint128 uiZ;
|
struct uint128 uiZ;
|
||||||
uiZ.v64 = defaultNaNF128UI64;
|
uiZ.v64 = defaultNaNF128UI64;
|
||||||
uiZ.v0 = defaultNaNF128UI0;
|
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
|
| If either original floating-point value is a signaling NaN, the invalid
|
||||||
| exception is raised.
|
| exception is raised.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
struct uint128
|
struct uint128 softfloat_propagateNaNF128UI(uint_fast64_t uiA64, uint_fast64_t uiA0, uint_fast64_t uiB64, uint_fast64_t uiB0);
|
||||||
softfloat_propagateNaNF128UI(
|
|
||||||
uint_fast64_t uiA64,
|
|
||||||
uint_fast64_t uiA0,
|
|
||||||
uint_fast64_t uiB64,
|
|
||||||
uint_fast64_t uiB0
|
|
||||||
);
|
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
@@ -315,7 +313,9 @@ struct uint128
|
|||||||
| common NaN at the location pointed to by 'zPtr'. If the NaN is a signaling
|
| common NaN at the location pointed to by 'zPtr'. If the NaN is a signaling
|
||||||
| NaN, the invalid exception is raised.
|
| 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
|
| 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
|
#if defined INLINE && !defined softfloat_commonNaNToExtF80M
|
||||||
INLINE
|
INLINE
|
||||||
void
|
void softfloat_commonNaNToExtF80M(const struct commonNaN* aPtr, struct extFloat80M* zSPtr) {
|
||||||
softfloat_commonNaNToExtF80M(
|
|
||||||
const struct commonNaN *aPtr, struct extFloat80M *zSPtr )
|
|
||||||
{
|
|
||||||
zSPtr->signExp = defaultNaNExtF80UI64;
|
zSPtr->signExp = defaultNaNExtF80UI64;
|
||||||
zSPtr->signif = defaultNaNExtF80UI0;
|
zSPtr->signif = defaultNaNExtF80UI0;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
void
|
void softfloat_commonNaNToExtF80M(const struct commonNaN* aPtr, struct extFloat80M* zSPtr);
|
||||||
softfloat_commonNaNToExtF80M(
|
|
||||||
const struct commonNaN *aPtr, struct extFloat80M *zSPtr );
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
@@ -343,12 +338,7 @@ void
|
|||||||
| at the location pointed to by 'zSPtr'. If either original floating-point
|
| at the location pointed to by 'zSPtr'. If either original floating-point
|
||||||
| value is a signaling NaN, the invalid exception is raised.
|
| value is a signaling NaN, the invalid exception is raised.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
void
|
void softfloat_propagateNaNExtF80M(const struct extFloat80M* aSPtr, const struct extFloat80M* bSPtr, struct extFloat80M* zSPtr);
|
||||||
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.
|
| 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
|
| four 32-bit elements that concatenate in the platform's normal endian order
|
||||||
| to form a 128-bit floating-point value.
|
| 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
|
| 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
|
#if defined INLINE && !defined softfloat_commonNaNToF128M
|
||||||
INLINE
|
INLINE
|
||||||
void
|
void softfloat_commonNaNToF128M(const struct commonNaN* aPtr, uint32_t* zWPtr) {
|
||||||
softfloat_commonNaNToF128M( const struct commonNaN *aPtr, uint32_t *zWPtr )
|
|
||||||
{
|
|
||||||
zWPtr[indexWord(4, 3)] = defaultNaNF128UI96;
|
zWPtr[indexWord(4, 3)] = defaultNaNF128UI96;
|
||||||
zWPtr[indexWord(4, 2)] = defaultNaNF128UI64;
|
zWPtr[indexWord(4, 2)] = defaultNaNF128UI64;
|
||||||
zWPtr[indexWord(4, 1)] = defaultNaNF128UI32;
|
zWPtr[indexWord(4, 1)] = defaultNaNF128UI32;
|
||||||
zWPtr[indexWord(4, 0)] = defaultNaNF128UI0;
|
zWPtr[indexWord(4, 0)] = defaultNaNF128UI0;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
void
|
void softfloat_commonNaNToF128M(const struct commonNaN* aPtr, uint32_t* zWPtr);
|
||||||
softfloat_commonNaNToF128M( const struct commonNaN *aPtr, uint32_t *zWPtr );
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
@@ -397,11 +386,8 @@ void
|
|||||||
| and 'zWPtr' points to an array of four 32-bit elements that concatenate in
|
| 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.
|
| the platform's normal endian order to form a 128-bit floating-point value.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
void
|
void softfloat_propagateNaNF128M(const uint32_t* aWPtr, const uint32_t* bWPtr, uint32_t* zWPtr);
|
||||||
softfloat_propagateNaNF128M(
|
|
||||||
const uint32_t *aWPtr, const uint32_t *bWPtr, uint32_t *zWPtr );
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -37,10 +37,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#ifndef specialize_h
|
#ifndef specialize_h
|
||||||
#define specialize_h 1
|
#define specialize_h 1
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include "primitiveTypes.h"
|
#include "primitiveTypes.h"
|
||||||
#include "softfloat.h"
|
#include "softfloat.h"
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
| Default value for 'softfloat_detectTininess'.
|
| 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
|
| the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a
|
||||||
| signaling NaN, the invalid exception is raised.
|
| signaling NaN, the invalid exception is raised.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
uint_fast16_t
|
uint_fast16_t softfloat_propagateNaNF16UI(uint_fast16_t uiA, uint_fast16_t uiB);
|
||||||
softfloat_propagateNaNF16UI( uint_fast16_t uiA, uint_fast16_t uiB );
|
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
| The bit pattern for a default generated 32-bit floating-point NaN.
|
| 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
|
| the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a
|
||||||
| signaling NaN, the invalid exception is raised.
|
| signaling NaN, the invalid exception is raised.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
uint_fast32_t
|
uint_fast32_t softfloat_propagateNaNF32UI(uint_fast32_t uiA, uint_fast32_t uiB);
|
||||||
softfloat_propagateNaNF32UI( uint_fast32_t uiA, uint_fast32_t uiB );
|
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
| The bit pattern for a default generated 64-bit floating-point NaN.
|
| 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.
|
| 64-bit floating-point signaling NaN.
|
||||||
| Note: This macro evaluates its argument more than once.
|
| 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
|
| 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
|
| the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a
|
||||||
| signaling NaN, the invalid exception is raised.
|
| signaling NaN, the invalid exception is raised.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
uint_fast64_t
|
uint_fast64_t softfloat_propagateNaNF64UI(uint_fast64_t uiA, uint_fast64_t uiB);
|
||||||
softfloat_propagateNaNF64UI( uint_fast64_t uiA, uint_fast64_t uiB );
|
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
| The bit pattern for a default generated 80-bit extended floating-point NaN.
|
| The bit pattern for a default generated 80-bit extended floating-point NaN.
|
||||||
@@ -199,7 +197,8 @@ uint_fast64_t
|
|||||||
| floating-point signaling NaN.
|
| floating-point signaling NaN.
|
||||||
| Note: This macro evaluates its arguments more than once.
|
| 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
|
#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
|
| location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid
|
||||||
| exception is raised.
|
| exception is raised.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
void
|
void softfloat_extF80UIToCommonNaN(uint_fast16_t uiA64, uint_fast64_t uiA0, struct commonNaN* zPtr);
|
||||||
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
|
| 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
|
| result. If either original floating-point value is a signaling NaN, the
|
||||||
| invalid exception is raised.
|
| invalid exception is raised.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
struct uint128
|
struct uint128 softfloat_propagateNaNExtF80UI(uint_fast16_t uiA64, uint_fast64_t uiA0, uint_fast16_t uiB64, uint_fast64_t uiB0);
|
||||||
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.
|
| The bit pattern for a default generated 128-bit floating-point NaN.
|
||||||
@@ -255,7 +246,8 @@ struct uint128
|
|||||||
| point signaling NaN.
|
| point signaling NaN.
|
||||||
| Note: This macro evaluates its arguments more than once.
|
| 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'
|
| 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
|
| pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid exception
|
||||||
| is raised.
|
| is raised.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
void
|
void softfloat_f128UIToCommonNaN(uint_fast64_t uiA64, uint_fast64_t uiA0, struct commonNaN* zPtr);
|
||||||
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
|
| 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
|
| If either original floating-point value is a signaling NaN, the invalid
|
||||||
| exception is raised.
|
| exception is raised.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
struct uint128
|
struct uint128 softfloat_propagateNaNF128UI(uint_fast64_t uiA64, uint_fast64_t uiA0, uint_fast64_t uiB64, uint_fast64_t uiB0);
|
||||||
softfloat_propagateNaNF128UI(
|
|
||||||
uint_fast64_t uiA64,
|
|
||||||
uint_fast64_t uiA0,
|
|
||||||
uint_fast64_t uiB64,
|
|
||||||
uint_fast64_t uiB0
|
|
||||||
);
|
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
@@ -304,18 +288,14 @@ struct uint128
|
|||||||
| common NaN at the location pointed to by 'zPtr'. If the NaN is a signaling
|
| common NaN at the location pointed to by 'zPtr'. If the NaN is a signaling
|
||||||
| NaN, the invalid exception is raised.
|
| NaN, the invalid exception is raised.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
void
|
void softfloat_extF80MToCommonNaN(const struct extFloat80M* aSPtr, struct commonNaN* zPtr);
|
||||||
softfloat_extF80MToCommonNaN(
|
|
||||||
const struct extFloat80M *aSPtr, struct commonNaN *zPtr );
|
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
| Converts the common NaN pointed to by 'aPtr' into an 80-bit extended
|
| 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
|
| floating-point NaN, and stores this NaN at the location pointed to by
|
||||||
| 'zSPtr'.
|
| 'zSPtr'.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
void
|
void softfloat_commonNaNToExtF80M(const struct commonNaN* aPtr, struct extFloat80M* zSPtr);
|
||||||
softfloat_commonNaNToExtF80M(
|
|
||||||
const struct commonNaN *aPtr, struct extFloat80M *zSPtr );
|
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
| Assuming at least one of the two 80-bit extended floating-point values
|
| 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
|
| at the location pointed to by 'zSPtr'. If either original floating-point
|
||||||
| value is a signaling NaN, the invalid exception is raised.
|
| value is a signaling NaN, the invalid exception is raised.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
void
|
void softfloat_propagateNaNExtF80M(const struct extFloat80M* aSPtr, const struct extFloat80M* bSPtr, struct extFloat80M* zSPtr);
|
||||||
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.
|
| 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
|
| four 32-bit elements that concatenate in the platform's normal endian order
|
||||||
| to form a 128-bit floating-point value.
|
| to form a 128-bit floating-point value.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
void
|
void softfloat_f128MToCommonNaN(const uint32_t* aWPtr, struct commonNaN* zPtr);
|
||||||
softfloat_f128MToCommonNaN( const uint32_t *aWPtr, struct commonNaN *zPtr );
|
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
| Converts the common NaN pointed to by 'aPtr' into a 128-bit floating-point
|
| 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
|
| '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.
|
| platform's normal endian order to form a 128-bit floating-point value.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
void
|
void softfloat_commonNaNToF128M(const struct commonNaN* aPtr, uint32_t* zWPtr);
|
||||||
softfloat_commonNaNToF128M( const struct commonNaN *aPtr, uint32_t *zWPtr );
|
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
| Assuming at least one of the two 128-bit floating-point values pointed to by
|
| 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
|
| 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.
|
| the platform's normal endian order to form a 128-bit floating-point value.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
void
|
void softfloat_propagateNaNF128M(const uint32_t* aWPtr, const uint32_t* bWPtr, uint32_t* zWPtr);
|
||||||
softfloat_propagateNaNF128M(
|
|
||||||
const uint32_t *aWPtr, const uint32_t *bWPtr, uint32_t *zWPtr );
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -37,10 +37,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#ifndef specialize_h
|
#ifndef specialize_h
|
||||||
#define specialize_h 1
|
#define specialize_h 1
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include "primitiveTypes.h"
|
#include "primitiveTypes.h"
|
||||||
#include "softfloat.h"
|
#include "softfloat.h"
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
| Default value for 'softfloat_detectTininess'.
|
| 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
|
| the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a
|
||||||
| signaling NaN, the invalid exception is raised.
|
| signaling NaN, the invalid exception is raised.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
uint_fast16_t
|
uint_fast16_t softfloat_propagateNaNF16UI(uint_fast16_t uiA, uint_fast16_t uiB);
|
||||||
softfloat_propagateNaNF16UI( uint_fast16_t uiA, uint_fast16_t uiB );
|
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
| The bit pattern for a default generated 32-bit floating-point NaN.
|
| 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
|
| the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a
|
||||||
| signaling NaN, the invalid exception is raised.
|
| signaling NaN, the invalid exception is raised.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
uint_fast32_t
|
uint_fast32_t softfloat_propagateNaNF32UI(uint_fast32_t uiA, uint_fast32_t uiB);
|
||||||
softfloat_propagateNaNF32UI( uint_fast32_t uiA, uint_fast32_t uiB );
|
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
| The bit pattern for a default generated 64-bit floating-point NaN.
|
| 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.
|
| 64-bit floating-point signaling NaN.
|
||||||
| Note: This macro evaluates its argument more than once.
|
| 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
|
| 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
|
| the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a
|
||||||
| signaling NaN, the invalid exception is raised.
|
| signaling NaN, the invalid exception is raised.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
uint_fast64_t
|
uint_fast64_t softfloat_propagateNaNF64UI(uint_fast64_t uiA, uint_fast64_t uiB);
|
||||||
softfloat_propagateNaNF64UI( uint_fast64_t uiA, uint_fast64_t uiB );
|
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
| The bit pattern for a default generated 80-bit extended floating-point NaN.
|
| The bit pattern for a default generated 80-bit extended floating-point NaN.
|
||||||
@@ -199,7 +197,8 @@ uint_fast64_t
|
|||||||
| floating-point signaling NaN.
|
| floating-point signaling NaN.
|
||||||
| Note: This macro evaluates its arguments more than once.
|
| 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
|
#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
|
| location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid
|
||||||
| exception is raised.
|
| exception is raised.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
void
|
void softfloat_extF80UIToCommonNaN(uint_fast16_t uiA64, uint_fast64_t uiA0, struct commonNaN* zPtr);
|
||||||
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
|
| 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
|
| result. If either original floating-point value is a signaling NaN, the
|
||||||
| invalid exception is raised.
|
| invalid exception is raised.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
struct uint128
|
struct uint128 softfloat_propagateNaNExtF80UI(uint_fast16_t uiA64, uint_fast64_t uiA0, uint_fast16_t uiB64, uint_fast64_t uiB0);
|
||||||
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.
|
| The bit pattern for a default generated 128-bit floating-point NaN.
|
||||||
@@ -255,7 +246,8 @@ struct uint128
|
|||||||
| point signaling NaN.
|
| point signaling NaN.
|
||||||
| Note: This macro evaluates its arguments more than once.
|
| 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'
|
| 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
|
| pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid exception
|
||||||
| is raised.
|
| is raised.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
void
|
void softfloat_f128UIToCommonNaN(uint_fast64_t uiA64, uint_fast64_t uiA0, struct commonNaN* zPtr);
|
||||||
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
|
| 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
|
| If either original floating-point value is a signaling NaN, the invalid
|
||||||
| exception is raised.
|
| exception is raised.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
struct uint128
|
struct uint128 softfloat_propagateNaNF128UI(uint_fast64_t uiA64, uint_fast64_t uiA0, uint_fast64_t uiB64, uint_fast64_t uiB0);
|
||||||
softfloat_propagateNaNF128UI(
|
|
||||||
uint_fast64_t uiA64,
|
|
||||||
uint_fast64_t uiA0,
|
|
||||||
uint_fast64_t uiB64,
|
|
||||||
uint_fast64_t uiB0
|
|
||||||
);
|
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
@@ -304,18 +288,14 @@ struct uint128
|
|||||||
| common NaN at the location pointed to by 'zPtr'. If the NaN is a signaling
|
| common NaN at the location pointed to by 'zPtr'. If the NaN is a signaling
|
||||||
| NaN, the invalid exception is raised.
|
| NaN, the invalid exception is raised.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
void
|
void softfloat_extF80MToCommonNaN(const struct extFloat80M* aSPtr, struct commonNaN* zPtr);
|
||||||
softfloat_extF80MToCommonNaN(
|
|
||||||
const struct extFloat80M *aSPtr, struct commonNaN *zPtr );
|
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
| Converts the common NaN pointed to by 'aPtr' into an 80-bit extended
|
| 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
|
| floating-point NaN, and stores this NaN at the location pointed to by
|
||||||
| 'zSPtr'.
|
| 'zSPtr'.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
void
|
void softfloat_commonNaNToExtF80M(const struct commonNaN* aPtr, struct extFloat80M* zSPtr);
|
||||||
softfloat_commonNaNToExtF80M(
|
|
||||||
const struct commonNaN *aPtr, struct extFloat80M *zSPtr );
|
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
| Assuming at least one of the two 80-bit extended floating-point values
|
| 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
|
| at the location pointed to by 'zSPtr'. If either original floating-point
|
||||||
| value is a signaling NaN, the invalid exception is raised.
|
| value is a signaling NaN, the invalid exception is raised.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
void
|
void softfloat_propagateNaNExtF80M(const struct extFloat80M* aSPtr, const struct extFloat80M* bSPtr, struct extFloat80M* zSPtr);
|
||||||
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.
|
| 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
|
| four 32-bit elements that concatenate in the platform's normal endian order
|
||||||
| to form a 128-bit floating-point value.
|
| to form a 128-bit floating-point value.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
void
|
void softfloat_f128MToCommonNaN(const uint32_t* aWPtr, struct commonNaN* zPtr);
|
||||||
softfloat_f128MToCommonNaN( const uint32_t *aWPtr, struct commonNaN *zPtr );
|
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
| Converts the common NaN pointed to by 'aPtr' into a 128-bit floating-point
|
| 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
|
| '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.
|
| platform's normal endian order to form a 128-bit floating-point value.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
void
|
void softfloat_commonNaNToF128M(const struct commonNaN* aPtr, uint32_t* zWPtr);
|
||||||
softfloat_commonNaNToF128M( const struct commonNaN *aPtr, uint32_t *zWPtr );
|
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
| Assuming at least one of the two 128-bit floating-point values pointed to by
|
| 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
|
| 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.
|
| the platform's normal endian order to form a 128-bit floating-point value.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
void
|
void softfloat_propagateNaNF128M(const uint32_t* aWPtr, const uint32_t* bWPtr, uint32_t* zWPtr);
|
||||||
softfloat_propagateNaNF128M(
|
|
||||||
const uint32_t *aWPtr, const uint32_t *bWPtr, uint32_t *zWPtr );
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -37,33 +37,43 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#ifndef internals_h
|
#ifndef internals_h
|
||||||
#define internals_h 1
|
#define internals_h 1
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include "primitives.h"
|
#include "primitives.h"
|
||||||
#include "softfloat_types.h"
|
#include "softfloat_types.h"
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
union ui16_f16 { uint16_t ui; float16_t f; };
|
union ui16_f16 {
|
||||||
union ui32_f32 { uint32_t ui; float32_t f; };
|
uint16_t ui;
|
||||||
union ui64_f64 { uint64_t ui; float64_t f; };
|
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
|
#ifdef SOFTFLOAT_FAST_INT64
|
||||||
union extF80M_extF80 { struct extFloat80M fM; extFloat80_t f; };
|
union extF80M_extF80 {
|
||||||
union ui128_f128 { struct uint128 ui; float128_t f; };
|
struct extFloat80M fM;
|
||||||
|
extFloat80_t f;
|
||||||
|
};
|
||||||
|
union ui128_f128 {
|
||||||
|
struct uint128 ui;
|
||||||
|
float128_t f;
|
||||||
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
enum {
|
enum { softfloat_mulAdd_subC = 1, softfloat_mulAdd_subProd = 2 };
|
||||||
softfloat_mulAdd_subC = 1,
|
|
||||||
softfloat_mulAdd_subProd = 2
|
|
||||||
};
|
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
uint_fast32_t softfloat_roundToUI32(bool, uint_fast64_t, uint_fast8_t, bool);
|
uint_fast32_t softfloat_roundToUI32(bool, uint_fast64_t, uint_fast8_t, bool);
|
||||||
|
|
||||||
#ifdef SOFTFLOAT_FAST_INT64
|
#ifdef SOFTFLOAT_FAST_INT64
|
||||||
uint_fast64_t
|
uint_fast64_t softfloat_roundToUI64(bool, uint_fast64_t, uint_fast64_t, uint_fast8_t, bool);
|
||||||
softfloat_roundToUI64(
|
|
||||||
bool, uint_fast64_t, uint_fast64_t, uint_fast8_t, bool );
|
|
||||||
#else
|
#else
|
||||||
uint_fast64_t softfloat_roundMToUI64(bool, uint32_t*, uint_fast8_t, bool);
|
uint_fast64_t softfloat_roundMToUI64(bool, uint32_t*, uint_fast8_t, bool);
|
||||||
#endif
|
#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);
|
int_fast32_t softfloat_roundToI32(bool, uint_fast64_t, uint_fast8_t, bool);
|
||||||
|
|
||||||
#ifdef SOFTFLOAT_FAST_INT64
|
#ifdef SOFTFLOAT_FAST_INT64
|
||||||
int_fast64_t
|
int_fast64_t softfloat_roundToI64(bool, uint_fast64_t, uint_fast64_t, uint_fast8_t, bool);
|
||||||
softfloat_roundToI64(
|
|
||||||
bool, uint_fast64_t, uint_fast64_t, uint_fast8_t, bool );
|
|
||||||
#else
|
#else
|
||||||
int_fast64_t softfloat_roundMToI64(bool, uint32_t*, uint_fast8_t, bool);
|
int_fast64_t softfloat_roundMToI64(bool, uint32_t*, uint_fast8_t, bool);
|
||||||
#endif
|
#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))
|
#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);
|
struct exp8_sig16 softfloat_normSubnormalF16Sig(uint_fast16_t);
|
||||||
|
|
||||||
float16_t softfloat_roundPackToF16(bool, int_fast16_t, 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_addMagsF16(uint_fast16_t, uint_fast16_t);
|
||||||
float16_t softfloat_subMagsF16(uint_fast16_t, uint_fast16_t);
|
float16_t softfloat_subMagsF16(uint_fast16_t, uint_fast16_t);
|
||||||
float16_t
|
float16_t softfloat_mulAddF16(uint_fast16_t, uint_fast16_t, uint_fast16_t, uint_fast8_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))
|
#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);
|
struct exp16_sig32 softfloat_normSubnormalF32Sig(uint_fast32_t);
|
||||||
|
|
||||||
float32_t softfloat_roundPackToF32(bool, int_fast16_t, 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_addMagsF32(uint_fast32_t, uint_fast32_t);
|
||||||
float32_t softfloat_subMagsF32(uint_fast32_t, uint_fast32_t);
|
float32_t softfloat_subMagsF32(uint_fast32_t, uint_fast32_t);
|
||||||
float32_t
|
float32_t softfloat_mulAddF32(uint_fast32_t, uint_fast32_t, uint_fast32_t, uint_fast8_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)))
|
#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);
|
struct exp16_sig64 softfloat_normSubnormalF64Sig(uint_fast64_t);
|
||||||
|
|
||||||
float64_t softfloat_roundPackToF64(bool, int_fast16_t, 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_addMagsF64(uint_fast64_t, uint_fast64_t, bool);
|
||||||
float64_t softfloat_subMagsF64(uint_fast64_t, uint_fast64_t, bool);
|
float64_t softfloat_subMagsF64(uint_fast64_t, uint_fast64_t, bool);
|
||||||
float64_t
|
float64_t softfloat_mulAddF64(uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast8_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);
|
struct exp32_sig64 softfloat_normSubnormalExtF80Sig(uint_fast64_t);
|
||||||
|
|
||||||
extFloat80_t
|
extFloat80_t softfloat_roundPackToExtF80(bool, int_fast32_t, uint_fast64_t, uint_fast64_t, uint_fast8_t);
|
||||||
softfloat_roundPackToExtF80(
|
extFloat80_t softfloat_normRoundPackToExtF80(bool, int_fast32_t, uint_fast64_t, uint_fast64_t, uint_fast8_t);
|
||||||
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
|
extFloat80_t softfloat_addMagsExtF80(uint_fast16_t, uint_fast64_t, uint_fast16_t, uint_fast64_t, bool);
|
||||||
softfloat_addMagsExtF80(
|
extFloat80_t softfloat_subMagsExtF80(uint_fast16_t, uint_fast64_t, uint_fast16_t, uint_fast64_t, bool);
|
||||||
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))))
|
#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 {
|
||||||
struct exp32_sig128
|
int_fast32_t exp;
|
||||||
softfloat_normSubnormalF128Sig( uint_fast64_t, uint_fast64_t );
|
struct uint128 sig;
|
||||||
|
};
|
||||||
|
struct exp32_sig128 softfloat_normSubnormalF128Sig(uint_fast64_t, uint_fast64_t);
|
||||||
|
|
||||||
float128_t
|
float128_t softfloat_roundPackToF128(bool, int_fast32_t, uint_fast64_t, uint_fast64_t, uint_fast64_t);
|
||||||
softfloat_roundPackToF128(
|
float128_t softfloat_normRoundPackToF128(bool, int_fast32_t, uint_fast64_t, uint_fast64_t);
|
||||||
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
|
float128_t softfloat_addMagsF128(uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast64_t, bool);
|
||||||
softfloat_addMagsF128(
|
float128_t softfloat_subMagsF128(uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast64_t, bool);
|
||||||
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_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
|
#else
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
bool
|
bool softfloat_tryPropagateNaNExtF80M(const struct extFloat80M*, const struct extFloat80M*, struct extFloat80M*);
|
||||||
softfloat_tryPropagateNaNExtF80M(
|
|
||||||
const struct extFloat80M *,
|
|
||||||
const struct extFloat80M *,
|
|
||||||
struct extFloat80M *
|
|
||||||
);
|
|
||||||
void softfloat_invalidExtF80M(struct extFloat80M*);
|
void softfloat_invalidExtF80M(struct extFloat80M*);
|
||||||
|
|
||||||
int softfloat_normExtF80SigM(uint64_t*);
|
int softfloat_normExtF80SigM(uint64_t*);
|
||||||
|
|
||||||
void
|
void softfloat_roundPackMToExtF80M(bool, int32_t, uint32_t*, uint_fast8_t, struct extFloat80M*);
|
||||||
softfloat_roundPackMToExtF80M(
|
void softfloat_normRoundPackMToExtF80M(bool, int32_t, uint32_t*, uint_fast8_t, struct extFloat80M*);
|
||||||
bool, int32_t, uint32_t *, uint_fast8_t, struct extFloat80M * );
|
|
||||||
void
|
|
||||||
softfloat_normRoundPackMToExtF80M(
|
|
||||||
bool, int32_t, uint32_t *, uint_fast8_t, struct extFloat80M * );
|
|
||||||
|
|
||||||
void
|
void softfloat_addExtF80M(const struct extFloat80M*, const struct extFloat80M*, struct extFloat80M*, bool);
|
||||||
softfloat_addExtF80M(
|
|
||||||
const struct extFloat80M *,
|
|
||||||
const struct extFloat80M *,
|
|
||||||
struct extFloat80M *,
|
|
||||||
bool
|
|
||||||
);
|
|
||||||
|
|
||||||
int
|
int softfloat_compareNonnormExtF80M(const struct extFloat80M*, const struct extFloat80M*);
|
||||||
softfloat_compareNonnormExtF80M(
|
|
||||||
const struct extFloat80M *, const struct extFloat80M * );
|
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
@@ -251,9 +225,7 @@ int
|
|||||||
|
|
||||||
bool softfloat_isNaNF128M(const uint32_t*);
|
bool softfloat_isNaNF128M(const uint32_t*);
|
||||||
|
|
||||||
bool
|
bool softfloat_tryPropagateNaNF128M(const uint32_t*, const uint32_t*, uint32_t*);
|
||||||
softfloat_tryPropagateNaNF128M(
|
|
||||||
const uint32_t *, const uint32_t *, uint32_t * );
|
|
||||||
void softfloat_invalidF128M(uint32_t*);
|
void softfloat_invalidF128M(uint32_t*);
|
||||||
|
|
||||||
int softfloat_shiftNormSigF128M(const uint32_t*, uint_fast8_t, uint32_t*);
|
int softfloat_shiftNormSigF128M(const uint32_t*, uint_fast8_t, uint32_t*);
|
||||||
@@ -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_roundPackMToF128M(bool, int32_t, uint32_t*, uint32_t*);
|
||||||
void softfloat_normRoundPackMToF128M(bool, int32_t, uint32_t*, uint32_t*);
|
void softfloat_normRoundPackMToF128M(bool, int32_t, uint32_t*, uint32_t*);
|
||||||
|
|
||||||
void
|
void softfloat_addF128M(const uint32_t*, const uint32_t*, uint32_t*, bool);
|
||||||
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_mulAddF128M(
|
|
||||||
const uint32_t *,
|
|
||||||
const uint32_t *,
|
|
||||||
const uint32_t *,
|
|
||||||
uint32_t *,
|
|
||||||
uint_fast8_t
|
|
||||||
);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -39,57 +39,57 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
#ifdef INLINE
|
#ifdef INLINE
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include "primitiveTypes.h"
|
#include "primitiveTypes.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
#ifdef SOFTFLOAT_BUILTIN_CLZ
|
#ifdef SOFTFLOAT_BUILTIN_CLZ
|
||||||
|
|
||||||
INLINE uint_fast8_t softfloat_countLeadingZeros16( uint16_t a )
|
INLINE uint_fast8_t softfloat_countLeadingZeros16(uint16_t a) { return a ? __builtin_clz(a) - 16 : 16; }
|
||||||
{ return a ? __builtin_clz( a ) - 16 : 16; }
|
|
||||||
#define softfloat_countLeadingZeros16 softfloat_countLeadingZeros16
|
#define softfloat_countLeadingZeros16 softfloat_countLeadingZeros16
|
||||||
|
|
||||||
INLINE uint_fast8_t softfloat_countLeadingZeros32( uint32_t a )
|
INLINE uint_fast8_t softfloat_countLeadingZeros32(uint32_t a) { return a ? __builtin_clz(a) : 32; }
|
||||||
{ return a ? __builtin_clz( a ) : 32; }
|
|
||||||
#define softfloat_countLeadingZeros32 softfloat_countLeadingZeros32
|
#define softfloat_countLeadingZeros32 softfloat_countLeadingZeros32
|
||||||
|
|
||||||
INLINE uint_fast8_t softfloat_countLeadingZeros64( uint64_t a )
|
INLINE uint_fast8_t softfloat_countLeadingZeros64(uint64_t a) { return a ? __builtin_clzll(a) : 64; }
|
||||||
{ return a ? __builtin_clzll( a ) : 64; }
|
|
||||||
#define softfloat_countLeadingZeros64 softfloat_countLeadingZeros64
|
#define softfloat_countLeadingZeros64 softfloat_countLeadingZeros64
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef SOFTFLOAT_INTRINSIC_INT128
|
#ifdef SOFTFLOAT_INTRINSIC_INT128
|
||||||
|
|
||||||
INLINE struct uint128 softfloat_mul64ByShifted32To128( uint64_t a, uint32_t b )
|
INLINE struct uint128 softfloat_mul64ByShifted32To128(uint64_t a, uint32_t b) {
|
||||||
{
|
union {
|
||||||
union { unsigned __int128 ui; struct uint128 s; } uZ;
|
unsigned __int128 ui;
|
||||||
|
struct uint128 s;
|
||||||
|
} uZ;
|
||||||
uZ.ui = (unsigned __int128)a * ((uint_fast64_t)b << 32);
|
uZ.ui = (unsigned __int128)a * ((uint_fast64_t)b << 32);
|
||||||
return uZ.s;
|
return uZ.s;
|
||||||
}
|
}
|
||||||
#define softfloat_mul64ByShifted32To128 softfloat_mul64ByShifted32To128
|
#define softfloat_mul64ByShifted32To128 softfloat_mul64ByShifted32To128
|
||||||
|
|
||||||
INLINE struct uint128 softfloat_mul64To128( uint64_t a, uint64_t b )
|
INLINE struct uint128 softfloat_mul64To128(uint64_t a, uint64_t b) {
|
||||||
{
|
union {
|
||||||
union { unsigned __int128 ui; struct uint128 s; } uZ;
|
unsigned __int128 ui;
|
||||||
|
struct uint128 s;
|
||||||
|
} uZ;
|
||||||
uZ.ui = (unsigned __int128)a * b;
|
uZ.ui = (unsigned __int128)a * b;
|
||||||
return uZ.s;
|
return uZ.s;
|
||||||
}
|
}
|
||||||
#define softfloat_mul64To128 softfloat_mul64To128
|
#define softfloat_mul64To128 softfloat_mul64To128
|
||||||
|
|
||||||
INLINE
|
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) {
|
||||||
{
|
union {
|
||||||
union { unsigned __int128 ui; struct uint128 s; } uZ;
|
unsigned __int128 ui;
|
||||||
|
struct uint128 s;
|
||||||
|
} uZ;
|
||||||
uZ.ui = ((unsigned __int128)a64 << 64 | a0) * b;
|
uZ.ui = ((unsigned __int128)a64 << 64 | a0) * b;
|
||||||
return uZ.s;
|
return uZ.s;
|
||||||
}
|
}
|
||||||
#define softfloat_mul128By32 softfloat_mul128By32
|
#define softfloat_mul128By32 softfloat_mul128By32
|
||||||
|
|
||||||
INLINE
|
INLINE
|
||||||
void
|
void softfloat_mul128To256M(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0, uint64_t* zPtr) {
|
||||||
softfloat_mul128To256M(
|
|
||||||
uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0, uint64_t *zPtr )
|
|
||||||
{
|
|
||||||
unsigned __int128 z0, mid1, mid, z128;
|
unsigned __int128 z0, mid1, mid, z128;
|
||||||
z0 = (unsigned __int128)a0 * b0;
|
z0 = (unsigned __int128)a0 * b0;
|
||||||
mid1 = (unsigned __int128)a64 * b0;
|
mid1 = (unsigned __int128)a64 * b0;
|
||||||
@@ -111,4 +111,3 @@ void
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -42,13 +42,27 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#ifdef SOFTFLOAT_FAST_INT64
|
#ifdef SOFTFLOAT_FAST_INT64
|
||||||
|
|
||||||
#ifdef LITTLEENDIAN
|
#ifdef LITTLEENDIAN
|
||||||
struct uint128 { uint64_t v0, v64; };
|
struct uint128 {
|
||||||
struct uint64_extra { uint64_t extra, v; };
|
uint64_t v0, v64;
|
||||||
struct uint128_extra { uint64_t extra; struct uint128 v; };
|
};
|
||||||
|
struct uint64_extra {
|
||||||
|
uint64_t extra, v;
|
||||||
|
};
|
||||||
|
struct uint128_extra {
|
||||||
|
uint64_t extra;
|
||||||
|
struct uint128 v;
|
||||||
|
};
|
||||||
#else
|
#else
|
||||||
struct uint128 { uint64_t v64, v0; };
|
struct uint128 {
|
||||||
struct uint64_extra { uint64_t v, extra; };
|
uint64_t v64, v0;
|
||||||
struct uint128_extra { struct uint128 v; uint64_t extra; };
|
};
|
||||||
|
struct uint64_extra {
|
||||||
|
uint64_t v, extra;
|
||||||
|
};
|
||||||
|
struct uint128_extra {
|
||||||
|
struct uint128 v;
|
||||||
|
uint64_t extra;
|
||||||
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -67,7 +81,8 @@ struct uint128_extra { struct uint128 v; uint64_t extra; };
|
|||||||
#define indexMultiwordLo(total, n) 0
|
#define indexMultiwordLo(total, n) 0
|
||||||
#define indexMultiwordHiBut(total, n) (n)
|
#define indexMultiwordHiBut(total, n) (n)
|
||||||
#define indexMultiwordLoBut(total, n) 0
|
#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
|
#else
|
||||||
#define wordIncr -1
|
#define wordIncr -1
|
||||||
#define indexWord(total, n) ((total)-1 - (n))
|
#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 indexMultiwordLo(total, n) ((total) - (n))
|
||||||
#define indexMultiwordHiBut(total, n) 0
|
#define indexMultiwordHiBut(total, n) 0
|
||||||
#define indexMultiwordLoBut(total, n) (n)
|
#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
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -37,9 +37,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#ifndef primitives_h
|
#ifndef primitives_h
|
||||||
#define primitives_h 1
|
#define primitives_h 1
|
||||||
|
|
||||||
|
#include "primitiveTypes.h"
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "primitiveTypes.h"
|
|
||||||
|
|
||||||
#ifndef softfloat_shortShiftRightJam64
|
#ifndef softfloat_shortShiftRightJam64
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
@@ -50,8 +50,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
|
#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
|
||||||
INLINE
|
INLINE
|
||||||
uint64_t softfloat_shortShiftRightJam64( uint64_t a, uint_fast8_t dist )
|
uint64_t softfloat_shortShiftRightJam64(uint64_t a, uint_fast8_t dist) { return a >> dist | ((a & (((uint_fast64_t)1 << dist) - 1)) != 0); }
|
||||||
{ return a>>dist | ((a & (((uint_fast64_t) 1<<dist) - 1)) != 0); }
|
|
||||||
#else
|
#else
|
||||||
uint64_t softfloat_shortShiftRightJam64(uint64_t a, uint_fast8_t dist);
|
uint64_t softfloat_shortShiftRightJam64(uint64_t a, uint_fast8_t dist);
|
||||||
#endif
|
#endif
|
||||||
@@ -68,10 +67,8 @@ uint64_t softfloat_shortShiftRightJam64( uint64_t a, uint_fast8_t dist );
|
|||||||
| is zero or nonzero.
|
| is zero or nonzero.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
|
#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
|
||||||
INLINE uint32_t softfloat_shiftRightJam32( uint32_t a, uint_fast16_t dist )
|
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);
|
||||||
return
|
|
||||||
(dist < 31) ? a>>dist | ((uint32_t) (a<<(-dist & 31)) != 0) : (a != 0);
|
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
uint32_t softfloat_shiftRightJam32(uint32_t a, uint_fast16_t dist);
|
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.
|
| is zero or nonzero.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
#if defined INLINE_LEVEL && (3 <= INLINE_LEVEL)
|
#if defined INLINE_LEVEL && (3 <= INLINE_LEVEL)
|
||||||
INLINE uint64_t softfloat_shiftRightJam64( uint64_t a, uint_fast32_t dist )
|
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);
|
||||||
return
|
|
||||||
(dist < 63) ? a>>dist | ((uint64_t) (a<<(-dist & 63)) != 0) : (a != 0);
|
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
uint64_t softfloat_shiftRightJam64(uint64_t a, uint_fast32_t dist);
|
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.
|
| 'a'. If 'a' is zero, 16 is returned.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
|
#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;
|
uint_fast8_t count = 8;
|
||||||
if(0x100 <= a) {
|
if(0x100 <= a) {
|
||||||
count = 0;
|
count = 0;
|
||||||
@@ -133,8 +127,7 @@ uint_fast8_t softfloat_countLeadingZeros16( uint16_t a );
|
|||||||
| 'a'. If 'a' is zero, 32 is returned.
|
| 'a'. If 'a' is zero, 32 is returned.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
#if defined INLINE_LEVEL && (3 <= INLINE_LEVEL)
|
#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;
|
uint_fast8_t count = 0;
|
||||||
if(a < 0x10000) {
|
if(a < 0x10000) {
|
||||||
count = 16;
|
count = 16;
|
||||||
@@ -222,8 +215,7 @@ uint32_t softfloat_approxRecipSqrt32_1( unsigned int oddExpA, uint32_t a );
|
|||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
#if defined INLINE_LEVEL && (1 <= INLINE_LEVEL)
|
#if defined INLINE_LEVEL && (1 <= INLINE_LEVEL)
|
||||||
INLINE
|
INLINE
|
||||||
bool softfloat_eq128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 )
|
bool softfloat_eq128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0) { return (a64 == b64) && (a0 == b0); }
|
||||||
{ return (a64 == b64) && (a0 == b0); }
|
|
||||||
#else
|
#else
|
||||||
bool softfloat_eq128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0);
|
bool softfloat_eq128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0);
|
||||||
#endif
|
#endif
|
||||||
@@ -237,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)
|
#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
|
||||||
INLINE
|
INLINE
|
||||||
bool softfloat_le128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 )
|
bool softfloat_le128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0) { return (a64 < b64) || ((a64 == b64) && (a0 <= b0)); }
|
||||||
{ return (a64 < b64) || ((a64 == b64) && (a0 <= b0)); }
|
|
||||||
#else
|
#else
|
||||||
bool softfloat_le128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0);
|
bool softfloat_le128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0);
|
||||||
#endif
|
#endif
|
||||||
@@ -252,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)
|
#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
|
||||||
INLINE
|
INLINE
|
||||||
bool softfloat_lt128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 )
|
bool softfloat_lt128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0) { return (a64 < b64) || ((a64 == b64) && (a0 < b0)); }
|
||||||
{ return (a64 < b64) || ((a64 == b64) && (a0 < b0)); }
|
|
||||||
#else
|
#else
|
||||||
bool softfloat_lt128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0);
|
bool softfloat_lt128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0);
|
||||||
#endif
|
#endif
|
||||||
@@ -266,17 +256,14 @@ bool softfloat_lt128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 );
|
|||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
|
#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
|
||||||
INLINE
|
INLINE
|
||||||
struct uint128
|
struct uint128 softfloat_shortShiftLeft128(uint64_t a64, uint64_t a0, uint_fast8_t dist) {
|
||||||
softfloat_shortShiftLeft128( uint64_t a64, uint64_t a0, uint_fast8_t dist )
|
|
||||||
{
|
|
||||||
struct uint128 z;
|
struct uint128 z;
|
||||||
z.v64 = a64 << dist | a0 >> (-dist & 63);
|
z.v64 = a64 << dist | a0 >> (-dist & 63);
|
||||||
z.v0 = a0 << dist;
|
z.v0 = a0 << dist;
|
||||||
return z;
|
return z;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
struct uint128
|
struct uint128 softfloat_shortShiftLeft128(uint64_t a64, uint64_t a0, uint_fast8_t dist);
|
||||||
softfloat_shortShiftLeft128( uint64_t a64, uint64_t a0, uint_fast8_t dist );
|
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -287,17 +274,14 @@ struct uint128
|
|||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
|
#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
|
||||||
INLINE
|
INLINE
|
||||||
struct uint128
|
struct uint128 softfloat_shortShiftRight128(uint64_t a64, uint64_t a0, uint_fast8_t dist) {
|
||||||
softfloat_shortShiftRight128( uint64_t a64, uint64_t a0, uint_fast8_t dist )
|
|
||||||
{
|
|
||||||
struct uint128 z;
|
struct uint128 z;
|
||||||
z.v64 = a64 >> dist;
|
z.v64 = a64 >> dist;
|
||||||
z.v0 = a64 << (-dist & 63) | a0 >> dist;
|
z.v0 = a64 << (-dist & 63) | a0 >> dist;
|
||||||
return z;
|
return z;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
struct uint128
|
struct uint128 softfloat_shortShiftRight128(uint64_t a64, uint64_t a0, uint_fast8_t dist);
|
||||||
softfloat_shortShiftRight128( uint64_t a64, uint64_t a0, uint_fast8_t dist );
|
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -308,19 +292,14 @@ struct uint128
|
|||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
|
#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
|
||||||
INLINE
|
INLINE
|
||||||
struct uint64_extra
|
struct uint64_extra softfloat_shortShiftRightJam64Extra(uint64_t a, uint64_t extra, uint_fast8_t dist) {
|
||||||
softfloat_shortShiftRightJam64Extra(
|
|
||||||
uint64_t a, uint64_t extra, uint_fast8_t dist )
|
|
||||||
{
|
|
||||||
struct uint64_extra z;
|
struct uint64_extra z;
|
||||||
z.v = a >> dist;
|
z.v = a >> dist;
|
||||||
z.extra = a << (-dist & 63) | (extra != 0);
|
z.extra = a << (-dist & 63) | (extra != 0);
|
||||||
return z;
|
return z;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
struct uint64_extra
|
struct uint64_extra softfloat_shortShiftRightJam64Extra(uint64_t a, uint64_t extra, uint_fast8_t dist);
|
||||||
softfloat_shortShiftRightJam64Extra(
|
|
||||||
uint64_t a, uint64_t extra, uint_fast8_t dist );
|
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -334,22 +313,15 @@ struct uint64_extra
|
|||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
#if defined INLINE_LEVEL && (3 <= INLINE_LEVEL)
|
#if defined INLINE_LEVEL && (3 <= INLINE_LEVEL)
|
||||||
INLINE
|
INLINE
|
||||||
struct uint128
|
struct uint128 softfloat_shortShiftRightJam128(uint64_t a64, uint64_t a0, uint_fast8_t dist) {
|
||||||
softfloat_shortShiftRightJam128(
|
|
||||||
uint64_t a64, uint64_t a0, uint_fast8_t dist )
|
|
||||||
{
|
|
||||||
uint_fast8_t negDist = -dist;
|
uint_fast8_t negDist = -dist;
|
||||||
struct uint128 z;
|
struct uint128 z;
|
||||||
z.v64 = a64 >> dist;
|
z.v64 = a64 >> dist;
|
||||||
z.v0 =
|
z.v0 = a64 << (negDist & 63) | a0 >> dist | ((uint64_t)(a0 << (negDist & 63)) != 0);
|
||||||
a64<<(negDist & 63) | a0>>dist
|
|
||||||
| ((uint64_t) (a0<<(negDist & 63)) != 0);
|
|
||||||
return z;
|
return z;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
struct uint128
|
struct uint128 softfloat_shortShiftRightJam128(uint64_t a64, uint64_t a0, uint_fast8_t dist);
|
||||||
softfloat_shortShiftRightJam128(
|
|
||||||
uint64_t a64, uint64_t a0, uint_fast8_t dist );
|
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -360,10 +332,7 @@ struct uint128
|
|||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
#if defined INLINE_LEVEL && (3 <= INLINE_LEVEL)
|
#if defined INLINE_LEVEL && (3 <= INLINE_LEVEL)
|
||||||
INLINE
|
INLINE
|
||||||
struct uint128_extra
|
struct uint128_extra softfloat_shortShiftRightJam128Extra(uint64_t a64, uint64_t a0, uint64_t extra, uint_fast8_t dist) {
|
||||||
softfloat_shortShiftRightJam128Extra(
|
|
||||||
uint64_t a64, uint64_t a0, uint64_t extra, uint_fast8_t dist )
|
|
||||||
{
|
|
||||||
uint_fast8_t negDist = -dist;
|
uint_fast8_t negDist = -dist;
|
||||||
struct uint128_extra z;
|
struct uint128_extra z;
|
||||||
z.v.v64 = a64 >> dist;
|
z.v.v64 = a64 >> dist;
|
||||||
@@ -372,9 +341,7 @@ struct uint128_extra
|
|||||||
return z;
|
return z;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
struct uint128_extra
|
struct uint128_extra softfloat_shortShiftRightJam128Extra(uint64_t a64, uint64_t a0, uint64_t extra, uint_fast8_t dist);
|
||||||
softfloat_shortShiftRightJam128Extra(
|
|
||||||
uint64_t a64, uint64_t a0, uint64_t extra, uint_fast8_t dist );
|
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -397,10 +364,7 @@ struct uint128_extra
|
|||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
#if defined INLINE_LEVEL && (4 <= INLINE_LEVEL)
|
#if defined INLINE_LEVEL && (4 <= INLINE_LEVEL)
|
||||||
INLINE
|
INLINE
|
||||||
struct uint64_extra
|
struct uint64_extra softfloat_shiftRightJam64Extra(uint64_t a, uint64_t extra, uint_fast32_t dist) {
|
||||||
softfloat_shiftRightJam64Extra(
|
|
||||||
uint64_t a, uint64_t extra, uint_fast32_t dist )
|
|
||||||
{
|
|
||||||
struct uint64_extra z;
|
struct uint64_extra z;
|
||||||
if(dist < 64) {
|
if(dist < 64) {
|
||||||
z.v = a >> dist;
|
z.v = a >> dist;
|
||||||
@@ -413,9 +377,7 @@ struct uint64_extra
|
|||||||
return z;
|
return z;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
struct uint64_extra
|
struct uint64_extra softfloat_shiftRightJam64Extra(uint64_t a, uint64_t extra, uint_fast32_t dist);
|
||||||
softfloat_shiftRightJam64Extra(
|
|
||||||
uint64_t a, uint64_t extra, uint_fast32_t dist );
|
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -430,8 +392,7 @@ struct uint64_extra
|
|||||||
| greater than 128, the result will be either 0 or 1, depending on whether the
|
| greater than 128, the result will be either 0 or 1, depending on whether the
|
||||||
| original 128 bits are all zeros.
|
| original 128 bits are all zeros.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
struct uint128
|
struct uint128 softfloat_shiftRightJam128(uint64_t a64, uint64_t a0, uint_fast32_t dist);
|
||||||
softfloat_shiftRightJam128( uint64_t a64, uint64_t a0, uint_fast32_t dist );
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef softfloat_shiftRightJam128Extra
|
#ifndef softfloat_shiftRightJam128Extra
|
||||||
@@ -452,9 +413,7 @@ struct uint128
|
|||||||
| is modified as described above and returned in the 'extra' field of the
|
| is modified as described above and returned in the 'extra' field of the
|
||||||
| result.)
|
| result.)
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
struct uint128_extra
|
struct uint128_extra softfloat_shiftRightJam128Extra(uint64_t a64, uint64_t a0, uint64_t extra, uint_fast32_t dist);
|
||||||
softfloat_shiftRightJam128Extra(
|
|
||||||
uint64_t a64, uint64_t a0, uint64_t extra, uint_fast32_t dist );
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef softfloat_shiftRightJam256M
|
#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
|
| is greater than 256, the stored result will be either 0 or 1, depending on
|
||||||
| whether the original 256 bits are all zeros.
|
| whether the original 256 bits are all zeros.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
void
|
void softfloat_shiftRightJam256M(const uint64_t* aPtr, uint_fast32_t dist, uint64_t* zPtr);
|
||||||
softfloat_shiftRightJam256M(
|
|
||||||
const uint64_t *aPtr, uint_fast32_t dist, uint64_t *zPtr );
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef softfloat_add128
|
#ifndef softfloat_add128
|
||||||
@@ -483,17 +440,14 @@ void
|
|||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
|
#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
|
||||||
INLINE
|
INLINE
|
||||||
struct uint128
|
struct uint128 softfloat_add128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0) {
|
||||||
softfloat_add128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 )
|
|
||||||
{
|
|
||||||
struct uint128 z;
|
struct uint128 z;
|
||||||
z.v0 = a0 + b0;
|
z.v0 = a0 + b0;
|
||||||
z.v64 = a64 + b64 + (z.v0 < a0);
|
z.v64 = a64 + b64 + (z.v0 < a0);
|
||||||
return z;
|
return z;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
struct uint128
|
struct uint128 softfloat_add128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0);
|
||||||
softfloat_add128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 );
|
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -505,9 +459,7 @@ struct uint128
|
|||||||
| an array of four 64-bit elements that concatenate in the platform's normal
|
| an array of four 64-bit elements that concatenate in the platform's normal
|
||||||
| endian order to form a 256-bit integer.
|
| endian order to form a 256-bit integer.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
void
|
void softfloat_add256M(const uint64_t* aPtr, const uint64_t* bPtr, uint64_t* zPtr);
|
||||||
softfloat_add256M(
|
|
||||||
const uint64_t *aPtr, const uint64_t *bPtr, uint64_t *zPtr );
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef softfloat_sub128
|
#ifndef softfloat_sub128
|
||||||
@@ -518,9 +470,7 @@ void
|
|||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
|
#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
|
||||||
INLINE
|
INLINE
|
||||||
struct uint128
|
struct uint128 softfloat_sub128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0) {
|
||||||
softfloat_sub128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 )
|
|
||||||
{
|
|
||||||
struct uint128 z;
|
struct uint128 z;
|
||||||
z.v0 = a0 - b0;
|
z.v0 = a0 - b0;
|
||||||
z.v64 = a64 - b64;
|
z.v64 = a64 - b64;
|
||||||
@@ -528,8 +478,7 @@ struct uint128
|
|||||||
return z;
|
return z;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
struct uint128
|
struct uint128 softfloat_sub128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0);
|
||||||
softfloat_sub128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 );
|
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -542,9 +491,7 @@ struct uint128
|
|||||||
| 64-bit elements that concatenate in the platform's normal endian order to
|
| 64-bit elements that concatenate in the platform's normal endian order to
|
||||||
| form a 256-bit integer.
|
| form a 256-bit integer.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
void
|
void softfloat_sub256M(const uint64_t* aPtr, const uint64_t* bPtr, uint64_t* zPtr);
|
||||||
softfloat_sub256M(
|
|
||||||
const uint64_t *aPtr, const uint64_t *bPtr, uint64_t *zPtr );
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef softfloat_mul64ByShifted32To128
|
#ifndef softfloat_mul64ByShifted32To128
|
||||||
@@ -552,8 +499,7 @@ void
|
|||||||
| Returns the 128-bit product of 'a', 'b', and 2^32.
|
| Returns the 128-bit product of 'a', 'b', and 2^32.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
#if defined INLINE_LEVEL && (3 <= INLINE_LEVEL)
|
#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;
|
uint_fast64_t mid;
|
||||||
struct uint128 z;
|
struct uint128 z;
|
||||||
mid = (uint_fast64_t)(uint32_t)a * b;
|
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)
|
#if defined INLINE_LEVEL && (4 <= INLINE_LEVEL)
|
||||||
INLINE
|
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;
|
struct uint128 z;
|
||||||
uint_fast64_t mid;
|
uint_fast64_t mid;
|
||||||
uint_fast32_t carry;
|
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
|
| 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.
|
| in the platform's normal endian order to form a 256-bit integer.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
void
|
void softfloat_mul128To256M(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0, uint64_t* zPtr);
|
||||||
softfloat_mul128To256M(
|
|
||||||
uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0, uint64_t *zPtr );
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#else
|
#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
|
| 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.
|
| concatenate in the platform's normal endian order to form a 128-bit integer.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
int_fast8_t
|
int_fast8_t softfloat_compare128M(const uint32_t* aPtr, const uint32_t* bPtr);
|
||||||
softfloat_compare128M( const uint32_t *aPtr, const uint32_t *bPtr );
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef softfloat_shortShiftLeft64To96M
|
#ifndef softfloat_shortShiftLeft64To96M
|
||||||
@@ -652,19 +594,14 @@ int_fast8_t
|
|||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
|
#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
|
||||||
INLINE
|
INLINE
|
||||||
void
|
void softfloat_shortShiftLeft64To96M(uint64_t a, uint_fast8_t dist, uint32_t* zPtr) {
|
||||||
softfloat_shortShiftLeft64To96M(
|
|
||||||
uint64_t a, uint_fast8_t dist, uint32_t *zPtr )
|
|
||||||
{
|
|
||||||
zPtr[indexWord(3, 0)] = (uint32_t)a << dist;
|
zPtr[indexWord(3, 0)] = (uint32_t)a << dist;
|
||||||
a >>= 32 - dist;
|
a >>= 32 - dist;
|
||||||
zPtr[indexWord(3, 2)] = a >> 32;
|
zPtr[indexWord(3, 2)] = a >> 32;
|
||||||
zPtr[indexWord(3, 1)] = a;
|
zPtr[indexWord(3, 1)] = a;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
void
|
void softfloat_shortShiftLeft64To96M(uint64_t a, uint_fast8_t dist, uint32_t* zPtr);
|
||||||
softfloat_shortShiftLeft64To96M(
|
|
||||||
uint64_t a, uint_fast8_t dist, uint32_t *zPtr );
|
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -678,13 +615,7 @@ void
|
|||||||
| that concatenate in the platform's normal endian order to form an N-bit
|
| that concatenate in the platform's normal endian order to form an N-bit
|
||||||
| integer.
|
| integer.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
void
|
void softfloat_shortShiftLeftM(uint_fast8_t size_words, const uint32_t* aPtr, uint_fast8_t dist, uint32_t* zPtr);
|
||||||
softfloat_shortShiftLeftM(
|
|
||||||
uint_fast8_t size_words,
|
|
||||||
const uint32_t *aPtr,
|
|
||||||
uint_fast8_t dist,
|
|
||||||
uint32_t *zPtr
|
|
||||||
);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef softfloat_shortShiftLeft96M
|
#ifndef softfloat_shortShiftLeft96M
|
||||||
@@ -722,13 +653,7 @@ void
|
|||||||
| The value of 'dist' can be arbitrarily large. In particular, if 'dist' is
|
| The value of 'dist' can be arbitrarily large. In particular, if 'dist' is
|
||||||
| greater than N, the stored result will be 0.
|
| greater than N, the stored result will be 0.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
void
|
void softfloat_shiftLeftM(uint_fast8_t size_words, const uint32_t* aPtr, uint32_t dist, uint32_t* zPtr);
|
||||||
softfloat_shiftLeftM(
|
|
||||||
uint_fast8_t size_words,
|
|
||||||
const uint32_t *aPtr,
|
|
||||||
uint32_t dist,
|
|
||||||
uint32_t *zPtr
|
|
||||||
);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef softfloat_shiftLeft96M
|
#ifndef softfloat_shiftLeft96M
|
||||||
@@ -765,13 +690,7 @@ void
|
|||||||
| that concatenate in the platform's normal endian order to form an N-bit
|
| that concatenate in the platform's normal endian order to form an N-bit
|
||||||
| integer.
|
| integer.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
void
|
void softfloat_shortShiftRightM(uint_fast8_t size_words, const uint32_t* aPtr, uint_fast8_t dist, uint32_t* zPtr);
|
||||||
softfloat_shortShiftRightM(
|
|
||||||
uint_fast8_t size_words,
|
|
||||||
const uint32_t *aPtr,
|
|
||||||
uint_fast8_t dist,
|
|
||||||
uint32_t *zPtr
|
|
||||||
);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef softfloat_shortShiftRight128M
|
#ifndef softfloat_shortShiftRight128M
|
||||||
@@ -801,9 +720,7 @@ void
|
|||||||
| to a 'size_words'-long array of 32-bit elements that concatenate in the
|
| 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.
|
| platform's normal endian order to form an N-bit integer.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
void
|
void softfloat_shortShiftRightJamM(uint_fast8_t, const uint32_t*, uint_fast8_t, uint32_t*);
|
||||||
softfloat_shortShiftRightJamM(
|
|
||||||
uint_fast8_t, const uint32_t *, uint_fast8_t, uint32_t * );
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef softfloat_shortShiftRightJam160M
|
#ifndef softfloat_shortShiftRightJam160M
|
||||||
@@ -825,13 +742,7 @@ void
|
|||||||
| The value of 'dist' can be arbitrarily large. In particular, if 'dist' is
|
| The value of 'dist' can be arbitrarily large. In particular, if 'dist' is
|
||||||
| greater than N, the stored result will be 0.
|
| greater than N, the stored result will be 0.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
void
|
void softfloat_shiftRightM(uint_fast8_t size_words, const uint32_t* aPtr, uint32_t dist, uint32_t* zPtr);
|
||||||
softfloat_shiftRightM(
|
|
||||||
uint_fast8_t size_words,
|
|
||||||
const uint32_t *aPtr,
|
|
||||||
uint32_t dist,
|
|
||||||
uint32_t *zPtr
|
|
||||||
);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef softfloat_shiftRight96M
|
#ifndef softfloat_shiftRight96M
|
||||||
@@ -856,13 +767,7 @@ void
|
|||||||
| is greater than N, the stored result will be either 0 or 1, depending on
|
| is greater than N, the stored result will be either 0 or 1, depending on
|
||||||
| whether the original N bits are all zeros.
|
| whether the original N bits are all zeros.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
void
|
void softfloat_shiftRightJamM(uint_fast8_t size_words, const uint32_t* aPtr, uint32_t dist, uint32_t* zPtr);
|
||||||
softfloat_shiftRightJamM(
|
|
||||||
uint_fast8_t size_words,
|
|
||||||
const uint32_t *aPtr,
|
|
||||||
uint32_t dist,
|
|
||||||
uint32_t *zPtr
|
|
||||||
);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef softfloat_shiftRightJam96M
|
#ifndef softfloat_shiftRightJam96M
|
||||||
@@ -898,13 +803,7 @@ void
|
|||||||
| elements that concatenate in the platform's normal endian order to form an
|
| elements that concatenate in the platform's normal endian order to form an
|
||||||
| N-bit integer.
|
| N-bit integer.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
void
|
void softfloat_addM(uint_fast8_t size_words, const uint32_t* aPtr, const uint32_t* bPtr, uint32_t* zPtr);
|
||||||
softfloat_addM(
|
|
||||||
uint_fast8_t size_words,
|
|
||||||
const uint32_t *aPtr,
|
|
||||||
const uint32_t *bPtr,
|
|
||||||
uint32_t *zPtr
|
|
||||||
);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef softfloat_add96M
|
#ifndef softfloat_add96M
|
||||||
@@ -940,14 +839,7 @@ void
|
|||||||
| points to a 'size_words'-long array of 32-bit elements that concatenate in
|
| 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.
|
| the platform's normal endian order to form an N-bit integer.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
uint_fast8_t
|
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);
|
||||||
softfloat_addCarryM(
|
|
||||||
uint_fast8_t size_words,
|
|
||||||
const uint32_t *aPtr,
|
|
||||||
const uint32_t *bPtr,
|
|
||||||
uint_fast8_t carry,
|
|
||||||
uint32_t *zPtr
|
|
||||||
);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef softfloat_addComplCarryM
|
#ifndef softfloat_addComplCarryM
|
||||||
@@ -956,14 +848,8 @@ uint_fast8_t
|
|||||||
| the value of the unsigned integer pointed to by 'bPtr' is bit-wise completed
|
| the value of the unsigned integer pointed to by 'bPtr' is bit-wise completed
|
||||||
| before the addition.
|
| before the addition.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
uint_fast8_t
|
uint_fast8_t softfloat_addComplCarryM(uint_fast8_t size_words, const uint32_t* aPtr, const uint32_t* bPtr, uint_fast8_t carry,
|
||||||
softfloat_addComplCarryM(
|
uint32_t* zPtr);
|
||||||
uint_fast8_t size_words,
|
|
||||||
const uint32_t *aPtr,
|
|
||||||
const uint32_t *bPtr,
|
|
||||||
uint_fast8_t carry,
|
|
||||||
uint32_t *zPtr
|
|
||||||
);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef softfloat_addComplCarry96M
|
#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
|
| array of 32-bit elements that concatenate in the platform's normal endian
|
||||||
| order to form an N-bit integer.
|
| order to form an N-bit integer.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
void
|
void softfloat_subM(uint_fast8_t size_words, const uint32_t* aPtr, const uint32_t* bPtr, uint32_t* zPtr);
|
||||||
softfloat_subM(
|
|
||||||
uint_fast8_t size_words,
|
|
||||||
const uint32_t *aPtr,
|
|
||||||
const uint32_t *bPtr,
|
|
||||||
uint32_t *zPtr
|
|
||||||
);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef softfloat_sub96M
|
#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
|
| Argument 'zPtr' points to an array of eight 32-bit elements that concatenate
|
||||||
| to form a 256-bit integer.
|
| to form a 256-bit integer.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
void
|
void softfloat_mul128MTo256M(const uint32_t* aPtr, const uint32_t* bPtr, uint32_t* zPtr);
|
||||||
softfloat_mul128MTo256M(
|
|
||||||
const uint32_t *aPtr, const uint32_t *bPtr, uint32_t *zPtr );
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef softfloat_remStepMBy32
|
#ifndef softfloat_remStepMBy32
|
||||||
@@ -1119,15 +997,8 @@ void
|
|||||||
| to a 'size_words'-long array of 32-bit elements that concatenate in the
|
| 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.
|
| platform's normal endian order to form an N-bit integer.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
void
|
void softfloat_remStepMBy32(uint_fast8_t size_words, const uint32_t* remPtr, uint_fast8_t dist, const uint32_t* bPtr, uint32_t q,
|
||||||
softfloat_remStepMBy32(
|
uint32_t* zPtr);
|
||||||
uint_fast8_t size_words,
|
|
||||||
const uint32_t *remPtr,
|
|
||||||
uint_fast8_t dist,
|
|
||||||
const uint32_t *bPtr,
|
|
||||||
uint32_t q,
|
|
||||||
uint32_t *zPtr
|
|
||||||
);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef softfloat_remStep96MBy32
|
#ifndef softfloat_remStep96MBy32
|
||||||
@@ -1157,4 +1028,3 @@ void
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#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
|
| 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
|
| 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.
|
| eliminates all dependencies on compile-time macros.
|
||||||
*============================================================================*/
|
*============================================================================*/
|
||||||
|
|
||||||
|
|
||||||
#ifndef softfloat_h
|
#ifndef softfloat_h
|
||||||
#define softfloat_h 1
|
#define softfloat_h 1
|
||||||
|
|
||||||
|
#include "softfloat_types.h"
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "softfloat_types.h"
|
|
||||||
|
|
||||||
#ifndef THREAD_LOCAL
|
#ifndef THREAD_LOCAL
|
||||||
#define 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.
|
| Software floating-point underflow tininess-detection mode.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
extern THREAD_LOCAL uint_fast8_t softfloat_detectTininess;
|
extern THREAD_LOCAL uint_fast8_t softfloat_detectTininess;
|
||||||
enum {
|
enum { softfloat_tininess_beforeRounding = 0, softfloat_tininess_afterRounding = 1 };
|
||||||
softfloat_tininess_beforeRounding = 0,
|
|
||||||
softfloat_tininess_afterRounding = 1
|
|
||||||
};
|
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
| Software floating-point rounding mode. (Mode "odd" is supported only if
|
| 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*);
|
float32_t extF80M_to_f32(const extFloat80_t*);
|
||||||
float64_t extF80M_to_f64(const extFloat80_t*);
|
float64_t extF80M_to_f64(const extFloat80_t*);
|
||||||
void extF80M_to_f128M(const extFloat80_t*, float128_t*);
|
void extF80M_to_f128M(const extFloat80_t*, float128_t*);
|
||||||
void
|
void extF80M_roundToInt(const extFloat80_t*, uint_fast8_t, bool, extFloat80_t*);
|
||||||
extF80M_roundToInt(
|
|
||||||
const extFloat80_t *, uint_fast8_t, bool, extFloat80_t * );
|
|
||||||
void extF80M_add(const extFloat80_t*, const extFloat80_t*, 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_sub(const extFloat80_t*, const extFloat80_t*, extFloat80_t*);
|
||||||
void extF80M_mul(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_add(const float128_t*, const float128_t*, float128_t*);
|
||||||
void f128M_sub(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_mul(const float128_t*, const float128_t*, float128_t*);
|
||||||
void
|
void f128M_mulAdd(const float128_t*, const float128_t*, const float128_t*, float128_t*);
|
||||||
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_div(const float128_t*, const float128_t*, float128_t*);
|
||||||
void f128M_rem(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*);
|
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*);
|
bool f128M_isSignalingNaN(const float128_t*);
|
||||||
|
|
||||||
#endif
|
#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
|
| the types below may, if desired, be defined as aliases for the native types
|
||||||
| (typically 'float' and 'double', and possibly 'long double').
|
| (typically 'float' and 'double', and possibly 'long double').
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
typedef struct { uint16_t v; } float16_t;
|
typedef struct {
|
||||||
typedef struct { uint32_t v; } float32_t;
|
uint16_t v;
|
||||||
typedef struct { uint64_t v; } float64_t;
|
} float16_t;
|
||||||
typedef struct { uint64_t v[2]; } float128_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
|
| 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'.
|
| named 'signif'.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
#ifdef LITTLEENDIAN
|
#ifdef LITTLEENDIAN
|
||||||
struct extFloat80M { uint64_t signif; uint16_t signExp; };
|
struct extFloat80M {
|
||||||
|
uint64_t signif;
|
||||||
|
uint16_t signExp;
|
||||||
|
};
|
||||||
#else
|
#else
|
||||||
struct extFloat80M { uint16_t signExp; uint64_t signif; };
|
struct extFloat80M {
|
||||||
|
uint16_t signExp;
|
||||||
|
uint64_t signif;
|
||||||
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
@@ -78,4 +92,3 @@ struct extFloat80M { uint16_t signExp; uint64_t signif; };
|
|||||||
typedef struct extFloat80M extFloat80_t;
|
typedef struct extFloat80M extFloat80_t;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
1
src-gen/.gitignore
vendored
1
src-gen/.gitignore
vendored
@@ -1,2 +1,3 @@
|
|||||||
/iss
|
/iss
|
||||||
/vm
|
/vm
|
||||||
|
/sysc
|
||||||
@@ -46,7 +46,7 @@ public:
|
|||||||
using this_class = hwl<BASE>;
|
using this_class = hwl<BASE>;
|
||||||
using reg_t = typename BASE::reg_t;
|
using reg_t = typename BASE::reg_t;
|
||||||
|
|
||||||
hwl();
|
hwl(feature_config cfg = feature_config{});
|
||||||
virtual ~hwl() = default;
|
virtual ~hwl() = default;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@@ -54,9 +54,9 @@ protected:
|
|||||||
iss::status write_custom_csr_reg(unsigned addr, reg_t val) override;
|
iss::status write_custom_csr_reg(unsigned addr, reg_t val) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
template <typename BASE>
|
template <typename BASE>
|
||||||
inline hwl<BASE>::hwl() {
|
inline hwl<BASE>::hwl(feature_config cfg)
|
||||||
|
: BASE(cfg) {
|
||||||
for(unsigned addr = 0x800; addr < 0x803; ++addr) {
|
for(unsigned addr = 0x800; addr < 0x803; ++addr) {
|
||||||
this->register_custom_csr_rd(addr);
|
this->register_custom_csr_rd(addr);
|
||||||
this->register_custom_csr_wr(addr);
|
this->register_custom_csr_wr(addr);
|
||||||
@@ -67,28 +67,50 @@ inline hwl<BASE>::hwl() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename BASE>
|
template <typename BASE> inline iss::status iss::arch::hwl<BASE>::read_custom_csr_reg(unsigned addr, reg_t& val) {
|
||||||
inline iss::status iss::arch::hwl<BASE>::read_custom_csr_reg(unsigned addr, reg_t &val) {
|
|
||||||
switch(addr) {
|
switch(addr) {
|
||||||
case 0x800: val = this->reg.lpstart0; break;
|
case 0x800:
|
||||||
case 0x801: val = this->reg.lpend0; break;
|
val = this->reg.lpstart0;
|
||||||
case 0x802: val = this->reg.lpcount0; break;
|
break;
|
||||||
case 0x804: val = this->reg.lpstart1; break;
|
case 0x801:
|
||||||
case 0x805: val = this->reg.lpend1; break;
|
val = this->reg.lpend0;
|
||||||
case 0x806: val = this->reg.lpcount1; break;
|
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;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename BASE>
|
template <typename BASE> inline iss::status iss::arch::hwl<BASE>::write_custom_csr_reg(unsigned addr, reg_t val) {
|
||||||
inline iss::status iss::arch::hwl<BASE>::write_custom_csr_reg(unsigned addr, reg_t val) {
|
|
||||||
switch(addr) {
|
switch(addr) {
|
||||||
case 0x800: this->reg.lpstart0 = val; break;
|
case 0x800:
|
||||||
case 0x801: this->reg.lpend0 = val; break;
|
this->reg.lpstart0 = val;
|
||||||
case 0x802: this->reg.lpcount0 = val; break;
|
break;
|
||||||
case 0x804: this->reg.lpstart1 = val; break;
|
case 0x801:
|
||||||
case 0x805: this->reg.lpend1 = val; break;
|
this->reg.lpend0 = val;
|
||||||
case 0x806: this->reg.lpcount1 = val; break;
|
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;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
@@ -96,5 +118,4 @@ inline iss::status iss::arch::hwl<BASE>::write_custom_csr_reg(unsigned addr, reg
|
|||||||
} // namespace arch
|
} // namespace arch
|
||||||
} // namespace iss
|
} // namespace iss
|
||||||
|
|
||||||
|
|
||||||
#endif /* _RISCV_HART_M_P_H */
|
#endif /* _RISCV_HART_M_P_H */
|
||||||
|
|||||||
@@ -175,7 +175,6 @@ enum riscv_csr {
|
|||||||
dscratch1 = 0x7B3
|
dscratch1 = 0x7B3
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
PGSHIFT = 12,
|
PGSHIFT = 12,
|
||||||
PTE_PPN_SHIFT = 10,
|
PTE_PPN_SHIFT = 10,
|
||||||
@@ -226,6 +225,8 @@ struct feature_config {
|
|||||||
unsigned clic_num_trigger{0};
|
unsigned clic_num_trigger{0};
|
||||||
uint64_t tcm_base{0x10000000};
|
uint64_t tcm_base{0x10000000};
|
||||||
uint64_t tcm_size{0x8000};
|
uint64_t tcm_size{0x8000};
|
||||||
|
uint64_t io_address{0xf0000000};
|
||||||
|
uint64_t io_addr_mask{0xf0000000};
|
||||||
};
|
};
|
||||||
|
|
||||||
class trap_load_access_fault : public trap_access {
|
class trap_load_access_fault : public trap_access {
|
||||||
@@ -296,7 +297,7 @@ inline void write_reg_uint32(uint64_t offs, uint32_t& reg, const uint8_t *const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
} // namespace arch
|
||||||
}
|
} // namespace iss
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -35,22 +35,22 @@
|
|||||||
#ifndef _RISCV_HART_M_P_H
|
#ifndef _RISCV_HART_M_P_H
|
||||||
#define _RISCV_HART_M_P_H
|
#define _RISCV_HART_M_P_H
|
||||||
|
|
||||||
#include "riscv_hart_common.h"
|
|
||||||
#include "iss/arch/traits.h"
|
#include "iss/arch/traits.h"
|
||||||
#include "iss/instrumentation_if.h"
|
#include "iss/instrumentation_if.h"
|
||||||
#include "iss/log_categories.h"
|
#include "iss/log_categories.h"
|
||||||
#include "iss/vm_if.h"
|
#include "iss/vm_if.h"
|
||||||
|
#include "riscv_hart_common.h"
|
||||||
#ifndef FMT_HEADER_ONLY
|
#ifndef FMT_HEADER_ONLY
|
||||||
#define FMT_HEADER_ONLY
|
#define FMT_HEADER_ONLY
|
||||||
#endif
|
#endif
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <elfio/elfio.hpp>
|
#include <elfio/elfio.hpp>
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
|
#include <functional>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <functional>
|
|
||||||
#include <util/bit_field.h>
|
#include <util/bit_field.h>
|
||||||
#include <util/ities.h>
|
#include <util/ities.h>
|
||||||
#include <util/sparse_array.h>
|
#include <util/sparse_array.h>
|
||||||
@@ -86,10 +86,11 @@ protected:
|
|||||||
"Load page fault", // d
|
"Load page fault", // d
|
||||||
"Reserved", // e
|
"Reserved", // e
|
||||||
"Store/AMO page fault"}};
|
"Store/AMO page fault"}};
|
||||||
const std::array<const char *, 12> irq_str = {
|
const std::array<const char*, 12> irq_str = {{"User software interrupt", "Supervisor software interrupt", "Reserved",
|
||||||
{"User software interrupt", "Supervisor software interrupt", "Reserved", "Machine software interrupt",
|
"Machine software interrupt", "User timer interrupt", "Supervisor timer interrupt",
|
||||||
"User timer interrupt", "Supervisor timer interrupt", "Reserved", "Machine timer interrupt",
|
"Reserved", "Machine timer interrupt", "User external interrupt",
|
||||||
"User external interrupt", "Supervisor external interrupt", "Reserved", "Machine external interrupt"}};
|
"Supervisor external interrupt", "Reserved", "Machine external interrupt"}};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using core = BASE;
|
using core = BASE;
|
||||||
using this_class = riscv_hart_m_p<BASE, FEAT>;
|
using this_class = riscv_hart_m_p<BASE, FEAT>;
|
||||||
@@ -108,7 +109,8 @@ public:
|
|||||||
template <typename T> class hart_state<T, typename std::enable_if<std::is_same<T, uint32_t>::value>::type> {
|
template <typename T> class hart_state<T, typename std::enable_if<std::is_same<T, uint32_t>::value>::type> {
|
||||||
public:
|
public:
|
||||||
BEGIN_BF_DECL(mstatus_t, T);
|
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);
|
BF_FIELD(SD, 31, 1);
|
||||||
// Trap SRET
|
// Trap SRET
|
||||||
BF_FIELD(TSR, 22, 1);
|
BF_FIELD(TSR, 22, 1);
|
||||||
@@ -122,7 +124,8 @@ public:
|
|||||||
BF_FIELD(SUM, 18, 1);
|
BF_FIELD(SUM, 18, 1);
|
||||||
// Modify PRiVilege
|
// Modify PRiVilege
|
||||||
BF_FIELD(MPRV, 17, 1);
|
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);
|
BF_FIELD(XS, 15, 2);
|
||||||
// floating-point unit status Off/Initial/Clean/Dirty
|
// floating-point unit status Off/Initial/Clean/Dirty
|
||||||
BF_FIELD(FS, 13, 2);
|
BF_FIELD(FS, 13, 2);
|
||||||
@@ -177,7 +180,8 @@ public:
|
|||||||
template <typename T> class hart_state<T, typename std::enable_if<std::is_same<T, uint64_t>::value>::type> {
|
template <typename T> class hart_state<T, typename std::enable_if<std::is_same<T, uint64_t>::value>::type> {
|
||||||
public:
|
public:
|
||||||
BEGIN_BF_DECL(mstatus_t, T);
|
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);
|
BF_FIELD(SD, 63, 1);
|
||||||
// value of XLEN for S-mode
|
// value of XLEN for S-mode
|
||||||
BF_FIELD(SXL, 34, 2);
|
BF_FIELD(SXL, 34, 2);
|
||||||
@@ -195,7 +199,8 @@ public:
|
|||||||
BF_FIELD(SUM, 18, 1);
|
BF_FIELD(SUM, 18, 1);
|
||||||
// Modify PRiVilege
|
// Modify PRiVilege
|
||||||
BF_FIELD(MPRV, 17, 1);
|
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);
|
BF_FIELD(XS, 15, 2);
|
||||||
// floating-point unit status Off/Initial/Clean/Dirty
|
// floating-point unit status Off/Initial/Clean/Dirty
|
||||||
BF_FIELD(FS, 13, 2);
|
BF_FIELD(FS, 13, 2);
|
||||||
@@ -252,12 +257,8 @@ public:
|
|||||||
return 0b100010001000; // only machine mode is supported
|
return 0b100010001000; // only machine mode is supported
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr bool has_compressed() {
|
constexpr bool has_compressed() { return traits<BASE>::MISA_VAL & 0b0100; }
|
||||||
return traits<BASE>::MISA_VAL&0b0100;
|
constexpr reg_t get_pc_mask() { return has_compressed() ? (reg_t)~1 : (reg_t)~3; }
|
||||||
}
|
|
||||||
constexpr reg_t get_pc_mask() {
|
|
||||||
return has_compressed()?(reg_t)~1:(reg_t)~3;
|
|
||||||
}
|
|
||||||
|
|
||||||
riscv_hart_m_p(feature_config cfg = feature_config{});
|
riscv_hart_m_p(feature_config cfg = feature_config{});
|
||||||
virtual ~riscv_hart_m_p() = default;
|
virtual ~riscv_hart_m_p() = default;
|
||||||
@@ -266,10 +267,10 @@ public:
|
|||||||
|
|
||||||
std::pair<uint64_t, bool> load_file(std::string name, int type = -1) override;
|
std::pair<uint64_t, bool> load_file(std::string name, int type = -1) override;
|
||||||
|
|
||||||
iss::status read(const address_type type, const access_type access, const uint32_t space,
|
iss::status read(const address_type type, const access_type access, const uint32_t space, const uint64_t addr, const unsigned length,
|
||||||
const uint64_t addr, const unsigned length, uint8_t *const data) override;
|
uint8_t* const data) override;
|
||||||
iss::status write(const address_type type, const access_type access, const uint32_t space,
|
iss::status write(const address_type type, const access_type access, const uint32_t space, const uint64_t addr, const unsigned length,
|
||||||
const uint64_t addr, const unsigned length, const uint8_t *const data) override;
|
const uint8_t* const data) override;
|
||||||
|
|
||||||
uint64_t enter_trap(uint64_t flags) override { return riscv_hart_m_p::enter_trap(flags, fault_data, fault_data); }
|
uint64_t enter_trap(uint64_t flags) override { return riscv_hart_m_p::enter_trap(flags, fault_data, fault_data); }
|
||||||
uint64_t enter_trap(uint64_t flags, uint64_t addr, uint64_t instr) override;
|
uint64_t enter_trap(uint64_t flags, uint64_t addr, uint64_t instr) override;
|
||||||
@@ -279,19 +280,16 @@ public:
|
|||||||
void set_mhartid(reg_t mhartid) { mhartid_reg = mhartid; };
|
void set_mhartid(reg_t mhartid) { mhartid_reg = mhartid; };
|
||||||
|
|
||||||
void disass_output(uint64_t pc, const std::string instr) override {
|
void disass_output(uint64_t pc, const std::string instr) override {
|
||||||
CLOG(INFO, disass) << fmt::format("0x{:016x} {:40} [s:0x{:x};c:{}]",
|
CLOG(INFO, disass) << fmt::format("0x{:016x} {:40} [s:0x{:x};c:{}]", pc, instr, (reg_t)state.mstatus,
|
||||||
pc, instr, (reg_t)state.mstatus, this->reg.icount + cycle_offset);
|
this->reg.icount + cycle_offset);
|
||||||
};
|
};
|
||||||
|
|
||||||
iss::instrumentation_if* get_instrumentation_if() override { return &instr_if; }
|
iss::instrumentation_if* get_instrumentation_if() override { return &instr_if; }
|
||||||
|
|
||||||
void set_csr(unsigned addr, reg_t val){
|
void set_csr(unsigned addr, reg_t val) { csr[addr & csr.page_addr_mask] = val; }
|
||||||
csr[addr & csr.page_addr_mask] = val;
|
|
||||||
}
|
void set_irq_num(unsigned i) { mcause_max_irq = 1 << util::ilog2(i); }
|
||||||
|
|
||||||
void set_irq_num(unsigned i) {
|
|
||||||
mcause_max_irq=1<<util::ilog2(i);
|
|
||||||
}
|
|
||||||
protected:
|
protected:
|
||||||
struct riscv_instrumentation_if : public iss::instrumentation_if {
|
struct riscv_instrumentation_if : public iss::instrumentation_if {
|
||||||
|
|
||||||
@@ -304,9 +302,9 @@ protected:
|
|||||||
*/
|
*/
|
||||||
const std::string core_type_name() const override { return traits<BASE>::core_type; }
|
const std::string core_type_name() const override { return traits<BASE>::core_type; }
|
||||||
|
|
||||||
uint64_t get_pc() override { return arch.reg.PC; };
|
uint64_t get_pc() override { return arch.reg.PC; }
|
||||||
|
|
||||||
uint64_t get_next_pc() override { return arch.reg.NEXT_PC; };
|
uint64_t get_next_pc() override { return arch.reg.NEXT_PC; }
|
||||||
|
|
||||||
uint64_t get_instr_word() override { return arch.reg.instruction; }
|
uint64_t get_instr_word() override { return arch.reg.instruction; }
|
||||||
|
|
||||||
@@ -316,9 +314,11 @@ protected:
|
|||||||
|
|
||||||
uint64_t get_total_cycles() override { return arch.reg.icount + arch.cycle_offset; }
|
uint64_t get_total_cycles() override { return arch.reg.icount + arch.cycle_offset; }
|
||||||
|
|
||||||
void update_last_instr_cycles(unsigned cycles) override { arch.cycle_offset += cycles - 1; };
|
void update_last_instr_cycles(unsigned cycles) override { arch.cycle_offset += cycles - 1; }
|
||||||
|
|
||||||
bool is_branch_taken() override { return arch.reg.last_branch; };
|
bool is_branch_taken() override { return arch.reg.last_branch; }
|
||||||
|
|
||||||
|
unsigned get_reg_num() override { return traits<BASE>::NUM_REGS; }
|
||||||
|
|
||||||
riscv_hart_m_p<BASE, FEAT>& arch;
|
riscv_hart_m_p<BASE, FEAT>& arch;
|
||||||
};
|
};
|
||||||
@@ -403,12 +403,8 @@ protected:
|
|||||||
virtual iss::status read_custom_csr_reg(unsigned addr, reg_t& val) { return iss::status::Err; };
|
virtual iss::status read_custom_csr_reg(unsigned addr, reg_t& val) { return iss::status::Err; };
|
||||||
virtual iss::status write_custom_csr_reg(unsigned addr, reg_t val) { return iss::status::Err; };
|
virtual iss::status write_custom_csr_reg(unsigned addr, reg_t val) { return iss::status::Err; };
|
||||||
|
|
||||||
void register_custom_csr_rd(unsigned addr){
|
void register_custom_csr_rd(unsigned addr) { csr_rd_cb[addr] = &this_class::read_custom_csr_reg; }
|
||||||
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_wr(unsigned addr){
|
|
||||||
csr_wr_cb[addr] = &this_class::write_custom_csr_reg;
|
|
||||||
}
|
|
||||||
|
|
||||||
reg_t mhartid_reg{0x0};
|
reg_t mhartid_reg{0x0};
|
||||||
|
|
||||||
@@ -421,8 +417,8 @@ protected:
|
|||||||
feature_config cfg;
|
feature_config cfg;
|
||||||
uint64_t mcause_max_irq{(FEAT & features_e::FEAT_CLIC) ? 4096 : 16};
|
uint64_t mcause_max_irq{(FEAT & features_e::FEAT_CLIC) ? 4096 : 16};
|
||||||
inline bool debug_mode_active() { return this->reg.PRIV & 0x4; }
|
inline bool debug_mode_active() { return this->reg.PRIV & 0x4; }
|
||||||
std::pair<std::function<mem_read_f>, std::function<mem_write_f>>
|
std::pair<std::function<mem_read_f>, std::function<mem_write_f>> replace_mem_access(std::function<mem_read_f> rd,
|
||||||
replace_mem_access(std::function<mem_read_f> rd, std::function<mem_write_f> wr){
|
std::function<mem_write_f> wr) {
|
||||||
std::pair<std::function<mem_read_f>, std::function<mem_write_f>> ret{hart_mem_rd_delegate, hart_mem_wr_delegate};
|
std::pair<std::function<mem_read_f>, std::function<mem_write_f>> ret{hart_mem_rd_delegate, hart_mem_wr_delegate};
|
||||||
hart_mem_rd_delegate = rd;
|
hart_mem_rd_delegate = rd;
|
||||||
hart_mem_wr_delegate = wr;
|
hart_mem_wr_delegate = wr;
|
||||||
@@ -448,7 +444,8 @@ riscv_hart_m_p<BASE, FEAT>::riscv_hart_m_p(feature_config cfg)
|
|||||||
csr_rd_cb[addr] = &this_class::read_null;
|
csr_rd_cb[addr] = &this_class::read_null;
|
||||||
csr_wr_cb[addr] = &this_class::write_csr_reg;
|
csr_wr_cb[addr] = &this_class::write_csr_reg;
|
||||||
}
|
}
|
||||||
if(traits<BASE>::XLEN==32) for (unsigned addr = mhpmcounter3h; addr <= mhpmcounter31h; ++addr){
|
if(traits<BASE>::XLEN == 32)
|
||||||
|
for(unsigned addr = mhpmcounter3h; addr <= mhpmcounter31h; ++addr) {
|
||||||
csr_rd_cb[addr] = &this_class::read_null;
|
csr_rd_cb[addr] = &this_class::read_null;
|
||||||
csr_wr_cb[addr] = &this_class::write_csr_reg;
|
csr_wr_cb[addr] = &this_class::write_csr_reg;
|
||||||
}
|
}
|
||||||
@@ -459,7 +456,8 @@ riscv_hart_m_p<BASE, FEAT>::riscv_hart_m_p(feature_config cfg)
|
|||||||
for(unsigned addr = hpmcounter3; addr <= hpmcounter31; ++addr) {
|
for(unsigned addr = hpmcounter3; addr <= hpmcounter31; ++addr) {
|
||||||
csr_rd_cb[addr] = &this_class::read_null;
|
csr_rd_cb[addr] = &this_class::read_null;
|
||||||
}
|
}
|
||||||
if(traits<BASE>::XLEN==32) for (unsigned addr = hpmcounter3h; addr <= hpmcounter31h; ++addr){
|
if(traits<BASE>::XLEN == 32)
|
||||||
|
for(unsigned addr = hpmcounter3h; addr <= hpmcounter31h; ++addr) {
|
||||||
csr_rd_cb[addr] = &this_class::read_null;
|
csr_rd_cb[addr] = &this_class::read_null;
|
||||||
// csr_wr_cb[addr] = &this_class::write_csr_reg;
|
// csr_wr_cb[addr] = &this_class::write_csr_reg;
|
||||||
}
|
}
|
||||||
@@ -476,20 +474,27 @@ riscv_hart_m_p<BASE, FEAT>::riscv_hart_m_p(feature_config cfg)
|
|||||||
}
|
}
|
||||||
// special handling & overrides
|
// special handling & overrides
|
||||||
csr_rd_cb[time] = &this_class::read_time;
|
csr_rd_cb[time] = &this_class::read_time;
|
||||||
if(traits<BASE>::XLEN==32) csr_rd_cb[timeh] = &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;
|
csr_rd_cb[cycle] = &this_class::read_cycle;
|
||||||
if(traits<BASE>::XLEN==32) csr_rd_cb[cycleh] = &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;
|
csr_rd_cb[instret] = &this_class::read_instret;
|
||||||
if(traits<BASE>::XLEN==32) csr_rd_cb[instreth] = &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_rd_cb[mcycle] = &this_class::read_cycle;
|
||||||
csr_wr_cb[mcycle] = &this_class::write_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)
|
||||||
if(traits<BASE>::XLEN==32) csr_wr_cb[mcycleh] = &this_class::write_cycle;
|
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_rd_cb[minstret] = &this_class::read_instret;
|
||||||
csr_wr_cb[minstret] = &this_class::write_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)
|
||||||
if(traits<BASE>::XLEN==32) csr_wr_cb[minstreth] = &this_class::write_instret;
|
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_rd_cb[mstatus] = &this_class::read_status;
|
||||||
csr_wr_cb[mstatus] = &this_class::write_status;
|
csr_wr_cb[mstatus] = &this_class::write_status;
|
||||||
csr_rd_cb[mcause] = &this_class::read_cause;
|
csr_rd_cb[mcause] = &this_class::read_cause;
|
||||||
@@ -522,7 +527,8 @@ riscv_hart_m_p<BASE, FEAT>::riscv_hart_m_p(feature_config cfg)
|
|||||||
clic_cfg_reg = 0x20;
|
clic_cfg_reg = 0x20;
|
||||||
clic_mact_lvl = clic_mprev_lvl = (1 << (cfg.clic_int_ctl_bits)) - 1;
|
clic_mact_lvl = clic_mprev_lvl = (1 << (cfg.clic_int_ctl_bits)) - 1;
|
||||||
csr[mintthresh] = (1 << (cfg.clic_int_ctl_bits)) - 1;
|
csr[mintthresh] = (1 << (cfg.clic_int_ctl_bits)) - 1;
|
||||||
insert_mem_range(cfg.clic_base, 0x5000UL,
|
insert_mem_range(
|
||||||
|
cfg.clic_base, 0x5000UL,
|
||||||
[this](phys_addr_t addr, unsigned length, uint8_t* const data) { return read_clic(addr.val, length, data); },
|
[this](phys_addr_t addr, unsigned length, uint8_t* const data) { return read_clic(addr.val, length, data); },
|
||||||
[this](phys_addr_t addr, unsigned length, uint8_t const* const data) { return write_clic(addr.val, length, data); });
|
[this](phys_addr_t addr, unsigned length, uint8_t const* const data) { return write_clic(addr.val, length, data); });
|
||||||
}
|
}
|
||||||
@@ -550,12 +556,8 @@ riscv_hart_m_p<BASE, FEAT>::riscv_hart_m_p(feature_config cfg)
|
|||||||
csr_wr_cb[dcsr] = &this_class::write_dcsr_dcsr;
|
csr_wr_cb[dcsr] = &this_class::write_dcsr_dcsr;
|
||||||
csr_rd_cb[dcsr] = &this_class::read_dcsr_reg;
|
csr_rd_cb[dcsr] = &this_class::read_dcsr_reg;
|
||||||
}
|
}
|
||||||
hart_mem_rd_delegate = [this](phys_addr_t a, unsigned l, uint8_t* const d) -> iss::status {
|
hart_mem_rd_delegate = [this](phys_addr_t a, unsigned l, uint8_t* const d) -> iss::status { return this->read_mem(a, l, d); };
|
||||||
return this->read_mem(a, l, d);
|
hart_mem_wr_delegate = [this](phys_addr_t a, unsigned l, uint8_t const* const d) -> iss::status { return this->write_mem(a, l, d); };
|
||||||
};
|
|
||||||
hart_mem_wr_delegate = [this](phys_addr_t a, unsigned l, uint8_t const* const d) -> iss::status {
|
|
||||||
return this->write_mem(a, l, d);
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT> std::pair<uint64_t, bool> riscv_hart_m_p<BASE, FEAT>::load_file(std::string name, int type) {
|
template <typename BASE, features_e FEAT> std::pair<uint64_t, bool> riscv_hart_m_p<BASE, FEAT>::load_file(std::string name, int type) {
|
||||||
@@ -564,35 +566,37 @@ template <typename BASE, features_e FEAT> std::pair<uint64_t, bool> riscv_hart_m
|
|||||||
std::array<char, 5> buf;
|
std::array<char, 5> buf;
|
||||||
auto n = fread(buf.data(), 1, 4, fp);
|
auto n = fread(buf.data(), 1, 4, fp);
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
if (n != 4) throw std::runtime_error("input file has insufficient size");
|
if(n != 4)
|
||||||
|
throw std::runtime_error("input file has insufficient size");
|
||||||
buf[4] = 0;
|
buf[4] = 0;
|
||||||
if(strcmp(buf.data() + 1, "ELF") == 0) {
|
if(strcmp(buf.data() + 1, "ELF") == 0) {
|
||||||
// Create elfio reader
|
// Create elfio reader
|
||||||
ELFIO::elfio reader;
|
ELFIO::elfio reader;
|
||||||
// Load ELF data
|
// 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
|
// check elf properties
|
||||||
if(reader.get_class() != ELFCLASS32)
|
if(reader.get_class() != ELFCLASS32)
|
||||||
if (sizeof(reg_t) == 4) throw std::runtime_error("wrong elf class in file");
|
if(sizeof(reg_t) == 4)
|
||||||
if (reader.get_type() != ET_EXEC) throw std::runtime_error("wrong elf type in file");
|
throw std::runtime_error("wrong elf class in file");
|
||||||
if (reader.get_machine() != EM_RISCV) throw std::runtime_error("wrong elf machine 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();
|
auto entry = reader.get_entry();
|
||||||
for(const auto pseg : reader.segments) {
|
for(const auto pseg : reader.segments) {
|
||||||
const auto fsize = pseg->get_file_size(); // 0x42c/0x0
|
const auto fsize = pseg->get_file_size(); // 0x42c/0x0
|
||||||
const auto seg_data = pseg->get_data();
|
const auto seg_data = pseg->get_data();
|
||||||
if(fsize > 0) {
|
if(fsize > 0) {
|
||||||
auto res = this->write(iss::address_type::PHYSICAL, iss::access_type::DEBUG_WRITE,
|
auto res = this->write(iss::address_type::PHYSICAL, iss::access_type::DEBUG_WRITE, traits<BASE>::MEM,
|
||||||
traits<BASE>::MEM, pseg->get_physical_address(),
|
pseg->get_physical_address(), fsize, reinterpret_cast<const uint8_t* const>(seg_data));
|
||||||
fsize, reinterpret_cast<const uint8_t *const>(seg_data));
|
|
||||||
if(res != iss::Ok)
|
if(res != iss::Ok)
|
||||||
LOG(ERR) << "problem writing " << fsize << "bytes to 0x" << std::hex
|
LOG(ERR) << "problem writing " << fsize << "bytes to 0x" << std::hex << pseg->get_physical_address();
|
||||||
<< pseg->get_physical_address();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for(const auto sec : reader.sections) {
|
for(const auto sec : reader.sections) {
|
||||||
if(sec->get_name() == ".symtab") {
|
if(sec->get_name() == ".symtab") {
|
||||||
if ( SHT_SYMTAB == sec->get_type() ||
|
if(SHT_SYMTAB == sec->get_type() || SHT_DYNSYM == sec->get_type()) {
|
||||||
SHT_DYNSYM == sec->get_type() ) {
|
|
||||||
ELFIO::symbol_section_accessor symbols(reader, sec);
|
ELFIO::symbol_section_accessor symbols(reader, sec);
|
||||||
auto sym_no = symbols.get_symbols_num();
|
auto sym_no = symbols.get_symbols_num();
|
||||||
std::string name;
|
std::string name;
|
||||||
@@ -615,7 +619,6 @@ template <typename BASE, features_e FEAT> std::pair<uint64_t, bool> riscv_hart_m
|
|||||||
tohost = sec->get_address();
|
tohost = sec->get_address();
|
||||||
fromhost = tohost + 0x40;
|
fromhost = tohost + 0x40;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
return std::make_pair(entry, true);
|
return std::make_pair(entry, true);
|
||||||
}
|
}
|
||||||
@@ -628,10 +631,9 @@ template<typename BASE, features_e FEAT>
|
|||||||
inline void riscv_hart_m_p<BASE, FEAT>::insert_mem_range(uint64_t base, uint64_t size, std::function<mem_read_f> rd_f,
|
inline void riscv_hart_m_p<BASE, FEAT>::insert_mem_range(uint64_t base, uint64_t size, std::function<mem_read_f> rd_f,
|
||||||
std::function<mem_write_f> wr_fn) {
|
std::function<mem_write_f> wr_fn) {
|
||||||
std::tuple<uint64_t, uint64_t> entry{base, size};
|
std::tuple<uint64_t, uint64_t> entry{base, size};
|
||||||
auto it = std::upper_bound( memfn_range.begin(), memfn_range.end(), entry,
|
auto it = std::upper_bound(
|
||||||
[](std::tuple<uint64_t, uint64_t> const& a, std::tuple<uint64_t, uint64_t> const& b){
|
memfn_range.begin(), memfn_range.end(), entry,
|
||||||
return std::get<0>(a)<std::get<0>(b);
|
[](std::tuple<uint64_t, uint64_t> const& a, std::tuple<uint64_t, uint64_t> const& b) { return std::get<0>(a) < std::get<0>(b); });
|
||||||
});
|
|
||||||
auto idx = std::distance(memfn_range.begin(), it);
|
auto idx = std::distance(memfn_range.begin(), it);
|
||||||
memfn_range.insert(it, entry);
|
memfn_range.insert(it, entry);
|
||||||
memfn_read.insert(std::begin(memfn_read) + idx, rd_f);
|
memfn_read.insert(std::begin(memfn_read) + idx, rd_f);
|
||||||
@@ -639,8 +641,8 @@ inline void riscv_hart_m_p<BASE, FEAT>::insert_mem_range(uint64_t base, uint64_t
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT>
|
template <typename BASE, features_e FEAT>
|
||||||
iss::status riscv_hart_m_p<BASE, FEAT>::read(const address_type type, const access_type access, const uint32_t space,
|
iss::status riscv_hart_m_p<BASE, FEAT>::read(const address_type type, const access_type access, const uint32_t space, const uint64_t addr,
|
||||||
const uint64_t addr, const unsigned length, uint8_t *const data) {
|
const unsigned length, uint8_t* const data) {
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if(access && iss::access_type::DEBUG) {
|
if(access && iss::access_type::DEBUG) {
|
||||||
LOG(TRACEALL) << "debug read of " << length << " bytes @addr 0x" << std::hex << addr;
|
LOG(TRACEALL) << "debug read of " << length << " bytes @addr 0x" << std::hex << addr;
|
||||||
@@ -656,7 +658,8 @@ iss::status riscv_hart_m_p<BASE, FEAT>::read(const address_type type, const acce
|
|||||||
auto alignment = is_fetch(access) ? (has_compressed() ? 2 : 4) : length;
|
auto alignment = is_fetch(access) ? (has_compressed() ? 2 : 4) : length;
|
||||||
if(unlikely(is_fetch(access) && (addr & (alignment - 1)))) {
|
if(unlikely(is_fetch(access) && (addr & (alignment - 1)))) {
|
||||||
fault_data = addr;
|
fault_data = addr;
|
||||||
if (is_debug(access)) throw trap_access(0, addr);
|
if(is_debug(access))
|
||||||
|
throw trap_access(0, addr);
|
||||||
this->reg.trap_state = (1UL << 31); // issue trap 0
|
this->reg.trap_state = (1UL << 31); // issue trap 0
|
||||||
return iss::Err;
|
return iss::Err;
|
||||||
}
|
}
|
||||||
@@ -666,10 +669,11 @@ iss::status riscv_hart_m_p<BASE, FEAT>::read(const address_type type, const acce
|
|||||||
fault_data = addr;
|
fault_data = addr;
|
||||||
return iss::Err;
|
return iss::Err;
|
||||||
}
|
}
|
||||||
auto phys_addr = type==iss::address_type::PHYSICAL?phys_addr_t{access, space, addr}:BASE::v2p(iss::addr_t{access, type, space, addr});
|
phys_addr_t phys_addr{access, space, addr};
|
||||||
auto res = iss::Err;
|
auto res = iss::Err;
|
||||||
if(access != access_type::FETCH && memfn_range.size()) {
|
if(access != access_type::FETCH && memfn_range.size()) {
|
||||||
auto it = std::find_if(std::begin(memfn_range), std::end(memfn_range), [phys_addr](std::tuple<uint64_t, uint64_t> const& a){
|
auto it =
|
||||||
|
std::find_if(std::begin(memfn_range), std::end(memfn_range), [phys_addr](std::tuple<uint64_t, uint64_t> const& a) {
|
||||||
return std::get<0>(a) <= phys_addr.val && (std::get<0>(a) + std::get<1>(a)) > phys_addr.val;
|
return std::get<0>(a) <= phys_addr.val && (std::get<0>(a) + std::get<1>(a)) > phys_addr.val;
|
||||||
});
|
});
|
||||||
if(it != std::end(memfn_range)) {
|
if(it != std::end(memfn_range)) {
|
||||||
@@ -680,7 +684,7 @@ iss::status riscv_hart_m_p<BASE, FEAT>::read(const address_type type, const acce
|
|||||||
} else {
|
} else {
|
||||||
res = hart_mem_rd_delegate(phys_addr, length, data);
|
res = hart_mem_rd_delegate(phys_addr, length, data);
|
||||||
}
|
}
|
||||||
if (unlikely(res != iss::Ok)){
|
if(unlikely(res != iss::Ok && (access & access_type::DEBUG) == 0)) {
|
||||||
this->reg.trap_state = (1UL << 31) | (5 << 16); // issue trap 5 (load access fault
|
this->reg.trap_state = (1UL << 31) | (5 << 16); // issue trap 5 (load access fault
|
||||||
fault_data = addr;
|
fault_data = addr;
|
||||||
}
|
}
|
||||||
@@ -692,11 +696,13 @@ iss::status riscv_hart_m_p<BASE, FEAT>::read(const address_type type, const acce
|
|||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case traits<BASE>::CSR: {
|
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));
|
return read_csr(addr, *reinterpret_cast<reg_t* const>(data));
|
||||||
} break;
|
} break;
|
||||||
case traits<BASE>::FENCE: {
|
case traits<BASE>::FENCE: {
|
||||||
if ((addr + length) > mem.size()) return iss::Err;
|
if((addr + length) > mem.size())
|
||||||
|
return iss::Err;
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
} break;
|
} break;
|
||||||
case traits<BASE>::RES: {
|
case traits<BASE>::RES: {
|
||||||
@@ -719,26 +725,26 @@ iss::status riscv_hart_m_p<BASE, FEAT>::read(const address_type type, const acce
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT>
|
template <typename BASE, features_e FEAT>
|
||||||
iss::status riscv_hart_m_p<BASE, FEAT>::write(const address_type type, const access_type access, const uint32_t space,
|
iss::status riscv_hart_m_p<BASE, FEAT>::write(const address_type type, const access_type access, const uint32_t space, const uint64_t addr,
|
||||||
const uint64_t addr, const unsigned length, const uint8_t *const data) {
|
const unsigned length, const uint8_t* const data) {
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
const char* prefix = (access && iss::access_type::DEBUG) ? "debug " : "";
|
const char* prefix = (access && iss::access_type::DEBUG) ? "debug " : "";
|
||||||
switch(length) {
|
switch(length) {
|
||||||
case 8:
|
case 8:
|
||||||
LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint64_t *)&data[0] << std::dec
|
LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint64_t*)&data[0] << std::dec << ") @addr 0x"
|
||||||
<< ") @addr 0x" << std::hex << addr;
|
<< std::hex << addr;
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint32_t *)&data[0] << std::dec
|
LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint32_t*)&data[0] << std::dec << ") @addr 0x"
|
||||||
<< ") @addr 0x" << std::hex << addr;
|
<< std::hex << addr;
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint16_t *)&data[0] << std::dec
|
LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint16_t*)&data[0] << std::dec << ") @addr 0x"
|
||||||
<< ") @addr 0x" << std::hex << addr;
|
<< std::hex << addr;
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << (uint16_t)data[0] << std::dec
|
LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << (uint16_t)data[0] << std::dec << ") @addr 0x"
|
||||||
<< ") @addr 0x" << std::hex << addr;
|
<< std::hex << addr;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
LOG(TRACE) << prefix << "write of " << length << " bytes @addr " << addr;
|
LOG(TRACE) << prefix << "write of " << length << " bytes @addr " << addr;
|
||||||
@@ -749,7 +755,8 @@ iss::status riscv_hart_m_p<BASE, FEAT>::write(const address_type type, const acc
|
|||||||
case traits<BASE>::MEM: {
|
case traits<BASE>::MEM: {
|
||||||
if(unlikely((access && iss::access_type::FETCH) && (addr & 0x1) == 1)) {
|
if(unlikely((access && iss::access_type::FETCH) && (addr & 0x1) == 1)) {
|
||||||
fault_data = addr;
|
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 = (1UL << 31); // issue trap 0
|
this->reg.trap_state = (1UL << 31); // issue trap 0
|
||||||
return iss::Err;
|
return iss::Err;
|
||||||
}
|
}
|
||||||
@@ -759,10 +766,11 @@ iss::status riscv_hart_m_p<BASE, FEAT>::write(const address_type type, const acc
|
|||||||
fault_data = addr;
|
fault_data = addr;
|
||||||
return iss::Err;
|
return iss::Err;
|
||||||
}
|
}
|
||||||
auto phys_addr = type==iss::address_type::PHYSICAL?phys_addr_t{access, space, addr}:BASE::v2p(iss::addr_t{access, type, space, addr});
|
phys_addr_t phys_addr{access, space, addr};
|
||||||
auto res = iss::Err;
|
auto res = iss::Err;
|
||||||
if(access != access_type::FETCH && memfn_range.size()) {
|
if(access != access_type::FETCH && memfn_range.size()) {
|
||||||
auto it = std::find_if(std::begin(memfn_range), std::end(memfn_range), [phys_addr](std::tuple<uint64_t, uint64_t> const& a){
|
auto it =
|
||||||
|
std::find_if(std::begin(memfn_range), std::end(memfn_range), [phys_addr](std::tuple<uint64_t, uint64_t> const& a) {
|
||||||
return std::get<0>(a) <= phys_addr.val && (std::get<0>(a) + std::get<1>(a)) > phys_addr.val;
|
return std::get<0>(a) <= phys_addr.val && (std::get<0>(a) + std::get<1>(a)) > phys_addr.val;
|
||||||
});
|
});
|
||||||
if(it != std::end(memfn_range)) {
|
if(it != std::end(memfn_range)) {
|
||||||
@@ -773,7 +781,7 @@ iss::status riscv_hart_m_p<BASE, FEAT>::write(const address_type type, const acc
|
|||||||
} else {
|
} else {
|
||||||
res = write_mem(phys_addr, length, data);
|
res = write_mem(phys_addr, length, data);
|
||||||
}
|
}
|
||||||
if (unlikely(res != iss::Ok)) {
|
if(unlikely(res != iss::Ok && (access & access_type::DEBUG) == 0)) {
|
||||||
this->reg.trap_state = (1UL << 31) | (7 << 16); // issue trap 7 (Store/AMO access fault)
|
this->reg.trap_state = (1UL << 31) | (7 << 16); // issue trap 7 (Store/AMO access fault)
|
||||||
fault_data = addr;
|
fault_data = addr;
|
||||||
}
|
}
|
||||||
@@ -784,9 +792,9 @@ iss::status riscv_hart_m_p<BASE, FEAT>::write(const address_type type, const acc
|
|||||||
return iss::Err;
|
return iss::Err;
|
||||||
}
|
}
|
||||||
|
|
||||||
phys_addr_t paddr = BASE::v2p(iss::addr_t{access, type, space, addr});
|
if((addr + length) > mem.size())
|
||||||
if ((paddr.val + length) > mem.size()) return iss::Err;
|
return iss::Err;
|
||||||
switch (paddr.val) {
|
switch(addr) {
|
||||||
case 0x10013000: // UART0 base, TXFIFO reg
|
case 0x10013000: // UART0 base, TXFIFO reg
|
||||||
case 0x10023000: // UART1 base, TXFIFO reg
|
case 0x10023000: // UART1 base, TXFIFO reg
|
||||||
uart_buf << (char)data[0];
|
uart_buf << (char)data[0];
|
||||||
@@ -798,16 +806,17 @@ iss::status riscv_hart_m_p<BASE, FEAT>::write(const address_type type, const acc
|
|||||||
}
|
}
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
case 0x10008000: { // HFROSC base, hfrosccfg reg
|
case 0x10008000: { // HFROSC base, hfrosccfg reg
|
||||||
auto &p = mem(paddr.val / mem.page_size);
|
auto& p = mem(addr / mem.page_size);
|
||||||
auto offs = paddr.val & mem.page_addr_mask;
|
auto offs = addr & mem.page_addr_mask;
|
||||||
std::copy(data, data + length, p.data() + offs);
|
std::copy(data, data + length, p.data() + offs);
|
||||||
auto& x = *(p.data() + offs + 3);
|
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;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
case 0x10008008: { // HFROSC base, pllcfg reg
|
case 0x10008008: { // HFROSC base, pllcfg reg
|
||||||
auto &p = mem(paddr.val / mem.page_size);
|
auto& p = mem(addr / mem.page_size);
|
||||||
auto offs = paddr.val & mem.page_addr_mask;
|
auto offs = addr & mem.page_addr_mask;
|
||||||
std::copy(data, data + length, p.data() + offs);
|
std::copy(data, data + length, p.data() + offs);
|
||||||
auto& x = *(p.data() + offs + 3);
|
auto& x = *(p.data() + offs + 3);
|
||||||
x |= 0x80; // set pll lock upon writing
|
x |= 0x80; // set pll lock upon writing
|
||||||
@@ -817,11 +826,13 @@ iss::status riscv_hart_m_p<BASE, FEAT>::write(const address_type type, const acc
|
|||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case traits<BASE>::CSR: {
|
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));
|
return write_csr(addr, *reinterpret_cast<const reg_t*>(data));
|
||||||
} break;
|
} break;
|
||||||
case traits<BASE>::FENCE: {
|
case traits<BASE>::FENCE: {
|
||||||
if ((addr + length) > mem.size()) return iss::Err;
|
if((addr + length) > mem.size())
|
||||||
|
return iss::Err;
|
||||||
switch(addr) {
|
switch(addr) {
|
||||||
case 2:
|
case 2:
|
||||||
case 3: {
|
case 3: {
|
||||||
@@ -846,7 +857,8 @@ iss::status riscv_hart_m_p<BASE, FEAT>::write(const address_type type, const acc
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT>::read_csr(unsigned addr, reg_t& val) {
|
template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT>::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;
|
auto req_priv_lvl = (addr >> 8) & 0x3;
|
||||||
if(this->reg.PRIV < req_priv_lvl) // not having required privileges
|
if(this->reg.PRIV < req_priv_lvl) // not having required privileges
|
||||||
throw illegal_instruction_fault(this->fault_data);
|
throw illegal_instruction_fault(this->fault_data);
|
||||||
@@ -857,7 +869,8 @@ template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT>
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT>::write_csr(unsigned addr, reg_t val) {
|
template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT>::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;
|
auto req_priv_lvl = (addr >> 8) & 0x3;
|
||||||
if(this->reg.PRIV < req_priv_lvl) // not having required privileges
|
if(this->reg.PRIV < req_priv_lvl) // not having required privileges
|
||||||
throw illegal_instruction_fault(this->fault_data);
|
throw illegal_instruction_fault(this->fault_data);
|
||||||
@@ -936,7 +949,8 @@ template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT>
|
|||||||
if(addr == time) {
|
if(addr == time) {
|
||||||
val = static_cast<reg_t>(time_val);
|
val = static_cast<reg_t>(time_val);
|
||||||
} else if(addr == timeh) {
|
} 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);
|
val = static_cast<reg_t>(time_val >> 32);
|
||||||
}
|
}
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
@@ -1051,20 +1065,17 @@ template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT>
|
|||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename BASE, features_e FEAT>
|
template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT>::read_intstatus(unsigned addr, reg_t& val) {
|
||||||
iss::status riscv_hart_m_p<BASE, FEAT>::read_intstatus(unsigned addr, reg_t& val) {
|
|
||||||
val = (clic_mact_lvl & 0xff) << 24;
|
val = (clic_mact_lvl & 0xff) << 24;
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename BASE, features_e FEAT>
|
template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT>::write_intthresh(unsigned addr, reg_t val) {
|
||||||
iss::status riscv_hart_m_p<BASE, FEAT>::write_intthresh(unsigned addr, reg_t val) {
|
|
||||||
csr[addr] = (val & 0xff) | (1 << (cfg.clic_int_ctl_bits)) - 1;
|
csr[addr] = (val & 0xff) | (1 << (cfg.clic_int_ctl_bits)) - 1;
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename BASE, features_e FEAT>
|
template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT>::write_xtvt(unsigned addr, reg_t val) {
|
||||||
iss::status riscv_hart_m_p<BASE, FEAT>::write_xtvt(unsigned addr, reg_t val) {
|
|
||||||
csr[addr] = val & ~0x3fULL;
|
csr[addr] = val & ~0x3fULL;
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
@@ -1096,10 +1107,9 @@ iss::status riscv_hart_m_p<BASE, FEAT>::write_mem(phys_addr_t paddr, unsigned le
|
|||||||
std::copy(data, data + length, p.data() + (paddr.val & mem.page_addr_mask));
|
std::copy(data, data + length, p.data() + (paddr.val & mem.page_addr_mask));
|
||||||
// tohost handling in case of riscv-test
|
// tohost handling in case of riscv-test
|
||||||
if(paddr.access && iss::access_type::FUNC) {
|
if(paddr.access && iss::access_type::FUNC) {
|
||||||
auto tohost_upper = (traits<BASE>::XLEN == 32 && paddr.val == (tohost + 4)) ||
|
auto tohost_upper =
|
||||||
(traits<BASE>::XLEN == 64 && paddr.val == tohost);
|
(traits<BASE>::XLEN == 32 && paddr.val == (tohost + 4)) || (traits<BASE>::XLEN == 64 && paddr.val == tohost);
|
||||||
auto tohost_lower =
|
auto tohost_lower = (traits<BASE>::XLEN == 32 && paddr.val == tohost) || (traits<BASE>::XLEN == 64 && paddr.val == tohost);
|
||||||
(traits<BASE>::XLEN == 32 && paddr.val == tohost) || (traits<BASE>::XLEN == 64 && paddr.val == tohost);
|
|
||||||
if(tohost_lower || tohost_upper) {
|
if(tohost_lower || tohost_upper) {
|
||||||
uint64_t hostvar = *reinterpret_cast<uint64_t*>(p.data() + (tohost & mem.page_addr_mask));
|
uint64_t hostvar = *reinterpret_cast<uint64_t*>(p.data() + (tohost & mem.page_addr_mask));
|
||||||
if(tohost_upper || (tohost_lower && to_host_wr_cnt > 0)) {
|
if(tohost_upper || (tohost_lower && to_host_wr_cnt > 0)) {
|
||||||
@@ -1114,8 +1124,10 @@ iss::status riscv_hart_m_p<BASE, FEAT>::write_mem(phys_addr_t paddr, unsigned le
|
|||||||
}
|
}
|
||||||
this->reg.trap_state = std::numeric_limits<uint32_t>::max();
|
this->reg.trap_state = std::numeric_limits<uint32_t>::max();
|
||||||
this->interrupt_sim = hostvar;
|
this->interrupt_sim = hostvar;
|
||||||
|
#ifndef WITH_TCC
|
||||||
|
throw(iss::simulation_stopped(hostvar));
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
//throw(iss::simulation_stopped(hostvar));
|
|
||||||
case 0x0101: {
|
case 0x0101: {
|
||||||
char c = static_cast<char>(hostvar & 0xff);
|
char c = static_cast<char>(hostvar & 0xff);
|
||||||
if(c == '\n' || c == 0) {
|
if(c == '\n' || c == 0) {
|
||||||
@@ -1130,8 +1142,7 @@ iss::status riscv_hart_m_p<BASE, FEAT>::write_mem(phys_addr_t paddr, unsigned le
|
|||||||
}
|
}
|
||||||
} else if(tohost_lower)
|
} else if(tohost_lower)
|
||||||
to_host_wr_cnt++;
|
to_host_wr_cnt++;
|
||||||
} else if ((traits<BASE>::XLEN == 32 && paddr.val == fromhost + 4) ||
|
} else if((traits<BASE>::XLEN == 32 && paddr.val == fromhost + 4) || (traits<BASE>::XLEN == 64 && paddr.val == fromhost)) {
|
||||||
(traits<BASE>::XLEN == 64 && paddr.val == fromhost)) {
|
|
||||||
uint64_t fhostvar = *reinterpret_cast<uint64_t*>(p.data() + (fromhost & mem.page_addr_mask));
|
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;
|
*reinterpret_cast<uint64_t*>(p.data() + (tohost & mem.page_addr_mask)) = fhostvar;
|
||||||
}
|
}
|
||||||
@@ -1145,15 +1156,18 @@ template<typename BASE, features_e FEAT>
|
|||||||
iss::status riscv_hart_m_p<BASE, FEAT>::read_clic(uint64_t addr, unsigned length, uint8_t* const data) {
|
iss::status riscv_hart_m_p<BASE, FEAT>::read_clic(uint64_t addr, unsigned length, uint8_t* const data) {
|
||||||
if(addr == cfg.clic_base) { // cliccfg
|
if(addr == cfg.clic_base) { // cliccfg
|
||||||
*data = clic_cfg_reg;
|
*data = clic_cfg_reg;
|
||||||
for(auto i=1; i<length; ++i) *(data+i)=0;
|
for(auto i = 1; i < length; ++i)
|
||||||
|
*(data + i) = 0;
|
||||||
} else if(addr >= (cfg.clic_base + 0x40) && (addr + length) <= (cfg.clic_base + 0x40 + cfg.clic_num_trigger * 4)) { // clicinttrig
|
} else if(addr >= (cfg.clic_base + 0x40) && (addr + length) <= (cfg.clic_base + 0x40 + cfg.clic_num_trigger * 4)) { // clicinttrig
|
||||||
auto offset = ((addr & 0x7fff) - 0x40) / 4;
|
auto offset = ((addr & 0x7fff) - 0x40) / 4;
|
||||||
read_reg_uint32(addr, clic_inttrig_reg[offset], data, length);
|
read_reg_uint32(addr, clic_inttrig_reg[offset], data, length);
|
||||||
} else if(addr>=(cfg.clic_base+0x1000) && (addr+length)<=(cfg.clic_base+0x1000+cfg.clic_num_irq*4)){ // clicintip/clicintie/clicintattr/clicintctl
|
} else if(addr >= (cfg.clic_base + 0x1000) &&
|
||||||
|
(addr + length) <= (cfg.clic_base + 0x1000 + cfg.clic_num_irq * 4)) { // clicintip/clicintie/clicintattr/clicintctl
|
||||||
auto offset = ((addr & 0x7fff) - 0x1000) / 4;
|
auto offset = ((addr & 0x7fff) - 0x1000) / 4;
|
||||||
read_reg_uint32(addr, clic_int_reg[offset].raw, data, length);
|
read_reg_uint32(addr, clic_int_reg[offset].raw, data, length);
|
||||||
} else {
|
} else {
|
||||||
for(auto i = 0U; i<length; ++i) *(data+i)=0;
|
for(auto i = 0U; i < length; ++i)
|
||||||
|
*(data + i) = 0;
|
||||||
}
|
}
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
@@ -1165,7 +1179,8 @@ iss::status riscv_hart_m_p<BASE, FEAT>::write_clic(uint64_t addr, unsigned lengt
|
|||||||
} else if(addr >= (cfg.clic_base + 0x40) && (addr + length) <= (cfg.clic_base + 0x40 + cfg.clic_num_trigger * 4)) { // clicinttrig
|
} else if(addr >= (cfg.clic_base + 0x40) && (addr + length) <= (cfg.clic_base + 0x40 + cfg.clic_num_trigger * 4)) { // clicinttrig
|
||||||
auto offset = ((addr & 0x7fff) - 0x40) / 4;
|
auto offset = ((addr & 0x7fff) - 0x40) / 4;
|
||||||
write_reg_uint32(addr, clic_inttrig_reg[offset], data, length);
|
write_reg_uint32(addr, clic_inttrig_reg[offset], data, length);
|
||||||
} else if(addr>=(cfg.clic_base+0x1000) && (addr+length)<=(cfg.clic_base+0x1000+cfg.clic_num_irq*4)){ // clicintip/clicintie/clicintattr/clicintctl
|
} else if(addr >= (cfg.clic_base + 0x1000) &&
|
||||||
|
(addr + length) <= (cfg.clic_base + 0x1000 + cfg.clic_num_irq * 4)) { // clicintip/clicintie/clicintattr/clicintctl
|
||||||
auto offset = ((addr & 0x7fff) - 0x1000) / 4;
|
auto offset = ((addr & 0x7fff) - 0x1000) / 4;
|
||||||
write_reg_uint32(addr, clic_int_reg[offset].raw, data, length);
|
write_reg_uint32(addr, clic_int_reg[offset].raw, data, length);
|
||||||
clic_int_reg[offset].raw &= 0xf0c70101; // clicIntCtlBits->0xf0, clicintattr->0xc7, clicintie->0x1, clicintip->0x1
|
clic_int_reg[offset].raw &= 0xf0c70101; // clicIntCtlBits->0xf0, clicintattr->0xc7, clicintie->0x1, clicintip->0x1
|
||||||
@@ -1209,7 +1224,8 @@ template <typename BASE, features_e FEAT> uint64_t riscv_hart_m_p<BASE, FEAT>::e
|
|||||||
// calculate effective privilege level
|
// calculate effective privilege level
|
||||||
unsigned new_priv = PRIV_M;
|
unsigned new_priv = PRIV_M;
|
||||||
if(trap_id == 0) { // exception
|
if(trap_id == 0) { // exception
|
||||||
if (cause == 11) cause = 0x8 + PRIV_M; // adjust environment call cause
|
if(cause == 11)
|
||||||
|
cause = 0x8 + PRIV_M; // adjust environment call cause
|
||||||
// store ret addr in xepc register
|
// store ret addr in xepc register
|
||||||
csr[mepc] = static_cast<reg_t>(addr) & get_pc_mask(); // store actual address instruction of exception
|
csr[mepc] = static_cast<reg_t>(addr) & get_pc_mask(); // store actual address instruction of exception
|
||||||
/*
|
/*
|
||||||
@@ -1271,7 +1287,8 @@ template <typename BASE, features_e FEAT> uint64_t riscv_hart_m_p<BASE, FEAT>::e
|
|||||||
} else {
|
} else {
|
||||||
// bits in mtvec
|
// bits in mtvec
|
||||||
this->reg.NEXT_PC = xtvec & ~0x3UL;
|
this->reg.NEXT_PC = xtvec & ~0x3UL;
|
||||||
if ((xtvec & 0x1) == 1 && trap_id != 0) this->reg.NEXT_PC += 4 * cause;
|
if((xtvec & 0x1) == 1 && trap_id != 0)
|
||||||
|
this->reg.NEXT_PC += 4 * cause;
|
||||||
}
|
}
|
||||||
// reset trap state
|
// reset trap state
|
||||||
this->reg.PRIV = new_priv;
|
this->reg.PRIV = new_priv;
|
||||||
@@ -1283,8 +1300,8 @@ template <typename BASE, features_e FEAT> uint64_t riscv_hart_m_p<BASE, FEAT>::e
|
|||||||
sprintf(buffer.data(), "0x%016lx", addr);
|
sprintf(buffer.data(), "0x%016lx", addr);
|
||||||
#endif
|
#endif
|
||||||
if((flags & 0xffffffff) != 0xffffffff)
|
if((flags & 0xffffffff) != 0xffffffff)
|
||||||
CLOG(INFO, disass) << (trap_id ? "Interrupt" : "Trap") << " with cause '"
|
CLOG(INFO, disass) << (trap_id ? "Interrupt" : "Trap") << " with cause '" << (trap_id ? irq_str[cause] : trap_str[cause]) << "' ("
|
||||||
<< (trap_id ? irq_str[cause] : trap_str[cause]) << "' (" << cause << ")"
|
<< cause << ")"
|
||||||
<< " at address " << buffer.data() << " occurred";
|
<< " at address " << buffer.data() << " occurred";
|
||||||
return this->reg.NEXT_PC;
|
return this->reg.NEXT_PC;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,22 +35,22 @@
|
|||||||
#ifndef _RISCV_HART_MSU_VP_H
|
#ifndef _RISCV_HART_MSU_VP_H
|
||||||
#define _RISCV_HART_MSU_VP_H
|
#define _RISCV_HART_MSU_VP_H
|
||||||
|
|
||||||
#include "riscv_hart_common.h"
|
|
||||||
#include "iss/arch/traits.h"
|
#include "iss/arch/traits.h"
|
||||||
#include "iss/instrumentation_if.h"
|
#include "iss/instrumentation_if.h"
|
||||||
#include "iss/log_categories.h"
|
#include "iss/log_categories.h"
|
||||||
#include "iss/vm_if.h"
|
#include "iss/vm_if.h"
|
||||||
|
#include "riscv_hart_common.h"
|
||||||
#ifndef FMT_HEADER_ONLY
|
#ifndef FMT_HEADER_ONLY
|
||||||
#define FMT_HEADER_ONLY
|
#define FMT_HEADER_ONLY
|
||||||
#endif
|
#endif
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <elfio/elfio.hpp>
|
#include <elfio/elfio.hpp>
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
|
#include <functional>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <functional>
|
|
||||||
#include <util/bit_field.h>
|
#include <util/bit_field.h>
|
||||||
#include <util/ities.h>
|
#include <util/ities.h>
|
||||||
#include <util/sparse_array.h>
|
#include <util/sparse_array.h>
|
||||||
@@ -86,10 +86,11 @@ protected:
|
|||||||
"Load page fault", // d
|
"Load page fault", // d
|
||||||
"Reserved", // e
|
"Reserved", // e
|
||||||
"Store/AMO page fault"}};
|
"Store/AMO page fault"}};
|
||||||
const std::array<const char *, 12> irq_str = {
|
const std::array<const char*, 12> irq_str = {{"User software interrupt", "Supervisor software interrupt", "Reserved",
|
||||||
{"User software interrupt", "Supervisor software interrupt", "Reserved", "Machine software interrupt",
|
"Machine software interrupt", "User timer interrupt", "Supervisor timer interrupt",
|
||||||
"User timer interrupt", "Supervisor timer interrupt", "Reserved", "Machine timer interrupt",
|
"Reserved", "Machine timer interrupt", "User external interrupt",
|
||||||
"User external interrupt", "Supervisor external interrupt", "Reserved", "Machine external interrupt"}};
|
"Supervisor external interrupt", "Reserved", "Machine external interrupt"}};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using core = BASE;
|
using core = BASE;
|
||||||
using this_class = riscv_hart_msu_vp<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> {
|
template <typename T> class hart_state<T, typename std::enable_if<std::is_same<T, uint32_t>::value>::type> {
|
||||||
public:
|
public:
|
||||||
BEGIN_BF_DECL(mstatus_t, T);
|
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);
|
BF_FIELD(SD, 31, 1);
|
||||||
// Trap SRET
|
// Trap SRET
|
||||||
BF_FIELD(TSR, 22, 1);
|
BF_FIELD(TSR, 22, 1);
|
||||||
@@ -121,7 +123,8 @@ public:
|
|||||||
BF_FIELD(SUM, 18, 1);
|
BF_FIELD(SUM, 18, 1);
|
||||||
// Modify PRiVilege
|
// Modify PRiVilege
|
||||||
BF_FIELD(MPRV, 17, 1);
|
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);
|
BF_FIELD(XS, 15, 2);
|
||||||
// floating-point unit status Off/Initial/Clean/Dirty
|
// floating-point unit status Off/Initial/Clean/Dirty
|
||||||
BF_FIELD(FS, 13, 2);
|
BF_FIELD(FS, 13, 2);
|
||||||
@@ -162,20 +165,27 @@ public:
|
|||||||
return priv_lvl == PRIV_U ? 0x80000011UL : priv_lvl == PRIV_S ? 0x800de133UL : 0x807ff9ddUL;
|
return priv_lvl == PRIV_U ? 0x80000011UL : priv_lvl == PRIV_S ? 0x800de133UL : 0x807ff9ddUL;
|
||||||
#else
|
#else
|
||||||
switch(priv_lvl) {
|
switch(priv_lvl) {
|
||||||
case PRIV_U: return 0x80000011UL; // 0b1000 0000 0000 0000 0000 0000 0001 0001
|
case PRIV_U:
|
||||||
case PRIV_S: return 0x800de133UL; // 0b1000 0000 0000 1101 1110 0001 0011 0011
|
return 0x80000011UL; // 0b1000 0000 0000 0000 0000 0000 0001 0001
|
||||||
default: return 0x807ff9ddUL; // 0b1000 0000 0111 1111 1111 1001 1011 1011
|
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
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline vm_info decode_vm_info(uint32_t state, T sptbr) {
|
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)
|
if(state <= PRIV_S)
|
||||||
switch(bit_sub<31, 1>(sptbr)) {
|
switch(bit_sub<31, 1>(sptbr)) {
|
||||||
case 0: return {0, 0, 0, 0}; // off
|
case 0:
|
||||||
case 1: return {2, 10, 4, bit_sub<0, 22>(sptbr) << PGSHIFT}; // SV32
|
return {0, 0, 0, 0}; // off
|
||||||
default: abort();
|
case 1:
|
||||||
|
return {2, 10, 4, bit_sub<0, 22>(sptbr) << PGSHIFT}; // SV32
|
||||||
|
default:
|
||||||
|
abort();
|
||||||
}
|
}
|
||||||
abort();
|
abort();
|
||||||
return {0, 0, 0, 0}; // dummy
|
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> {
|
template <typename T> class hart_state<T, typename std::enable_if<std::is_same<T, uint64_t>::value>::type> {
|
||||||
public:
|
public:
|
||||||
BEGIN_BF_DECL(mstatus_t, T);
|
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);
|
BF_FIELD(SD, 63, 1);
|
||||||
// value of XLEN for S-mode
|
// value of XLEN for S-mode
|
||||||
BF_FIELD(SXL, 34, 2);
|
BF_FIELD(SXL, 34, 2);
|
||||||
@@ -203,7 +214,8 @@ public:
|
|||||||
BF_FIELD(SUM, 18, 1);
|
BF_FIELD(SUM, 18, 1);
|
||||||
// Modify PRiVilege
|
// Modify PRiVilege
|
||||||
BF_FIELD(MPRV, 17, 1);
|
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);
|
BF_FIELD(XS, 15, 2);
|
||||||
// floating-point unit status Off/Initial/Clean/Dirty
|
// floating-point unit status Off/Initial/Clean/Dirty
|
||||||
BF_FIELD(FS, 13, 2);
|
BF_FIELD(FS, 13, 2);
|
||||||
@@ -249,23 +261,36 @@ public:
|
|||||||
static constexpr T get_mask(unsigned priv_lvl) {
|
static constexpr T get_mask(unsigned priv_lvl) {
|
||||||
uint64_t ret;
|
uint64_t ret;
|
||||||
switch(priv_lvl) {
|
switch(priv_lvl) {
|
||||||
case PRIV_U: ret = 0x8000000f00000011ULL;break; // 0b1...0 1111 0000 0000 0111 1111 1111 1001 1011 1011
|
case PRIV_U:
|
||||||
case PRIV_S: ret = 0x8000000f000de133ULL;break; // 0b1...0 0011 0000 0000 0000 1101 1110 0001 0011 0011
|
ret = 0x8000000f00000011ULL;
|
||||||
default: ret = 0x8000000f007ff9ddULL;break; // 0b1...0 1111 0000 0000 0111 1111 1111 1001 1011 1011
|
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;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline vm_info decode_vm_info(uint32_t state, T sptbr) {
|
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)
|
if(state <= PRIV_S)
|
||||||
switch(bit_sub<60, 4>(sptbr)) {
|
switch(bit_sub<60, 4>(sptbr)) {
|
||||||
case 0: return {0, 0, 0, 0}; // off
|
case 0:
|
||||||
case 8: return {3, 9, 8, bit_sub<0, 44>(sptbr) << PGSHIFT};// SV39
|
return {0, 0, 0, 0}; // off
|
||||||
case 9: return {4, 9, 8, bit_sub<0, 44>(sptbr) << PGSHIFT};// SV48
|
case 8:
|
||||||
case 10: return {5, 9, 8, bit_sub<0, 44>(sptbr) << PGSHIFT};// SV57
|
return {3, 9, 8, bit_sub<0, 44>(sptbr) << PGSHIFT}; // SV39
|
||||||
case 11: return {6, 9, 8, bit_sub<0, 44>(sptbr) << PGSHIFT};// SV64
|
case 9:
|
||||||
default: abort();
|
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();
|
abort();
|
||||||
return {0, 0, 0, 0}; // dummy
|
return {0, 0, 0, 0}; // dummy
|
||||||
@@ -286,7 +311,7 @@ public:
|
|||||||
return m[mode];
|
return m[mode];
|
||||||
}
|
}
|
||||||
|
|
||||||
riscv_hart_msu_vp();
|
riscv_hart_msu_vp(feature_config cfg = feature_config{});
|
||||||
virtual ~riscv_hart_msu_vp() = default;
|
virtual ~riscv_hart_msu_vp() = default;
|
||||||
|
|
||||||
void reset(uint64_t address) override;
|
void reset(uint64_t address) override;
|
||||||
@@ -295,10 +320,10 @@ public:
|
|||||||
|
|
||||||
phys_addr_t virt2phys(const iss::addr_t& addr) override;
|
phys_addr_t virt2phys(const iss::addr_t& addr) override;
|
||||||
|
|
||||||
iss::status read(const address_type type, const access_type access, const uint32_t space,
|
iss::status read(const address_type type, const access_type access, const uint32_t space, const uint64_t addr, const unsigned length,
|
||||||
const uint64_t addr, const unsigned length, uint8_t *const data) override;
|
uint8_t* const data) override;
|
||||||
iss::status write(const address_type type, const access_type access, const uint32_t space,
|
iss::status write(const address_type type, const access_type access, const uint32_t space, const uint64_t addr, const unsigned length,
|
||||||
const uint64_t addr, const unsigned length, const uint8_t *const data) override;
|
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) 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;
|
uint64_t enter_trap(uint64_t flags, uint64_t addr, uint64_t instr) override;
|
||||||
@@ -306,19 +331,16 @@ public:
|
|||||||
void wait_until(uint64_t flags) override;
|
void wait_until(uint64_t flags) override;
|
||||||
|
|
||||||
void disass_output(uint64_t pc, const std::string instr) 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:{}]",
|
CLOG(INFO, disass) << fmt::format("0x{:016x} {:40} [p:{};s:0x{:x};c:{}]", pc, instr, lvl[this->reg.PRIV], (reg_t)state.mstatus,
|
||||||
pc, instr, lvl[this->reg.PRIV], (reg_t)state.mstatus, this->reg.icount + cycle_offset);
|
this->reg.icount + cycle_offset);
|
||||||
};
|
};
|
||||||
|
|
||||||
iss::instrumentation_if* get_instrumentation_if() override { return &instr_if; }
|
iss::instrumentation_if* get_instrumentation_if() override { return &instr_if; }
|
||||||
|
|
||||||
void set_csr(unsigned addr, reg_t val){
|
void set_csr(unsigned addr, reg_t val) { csr[addr & csr.page_addr_mask] = val; }
|
||||||
csr[addr & csr.page_addr_mask] = val;
|
|
||||||
}
|
void set_irq_num(unsigned i) { mcause_max_irq = 1 << util::ilog2(i); }
|
||||||
|
|
||||||
void set_irq_num(unsigned i) {
|
|
||||||
mcause_max_irq=1<<util::ilog2(i);
|
|
||||||
}
|
|
||||||
protected:
|
protected:
|
||||||
struct riscv_instrumentation_if : public iss::instrumentation_if {
|
struct riscv_instrumentation_if : public iss::instrumentation_if {
|
||||||
|
|
||||||
@@ -331,9 +353,9 @@ protected:
|
|||||||
*/
|
*/
|
||||||
const std::string core_type_name() const override { return traits<BASE>::core_type; }
|
const std::string core_type_name() const override { return traits<BASE>::core_type; }
|
||||||
|
|
||||||
uint64_t get_pc() override { return arch.reg.PC; };
|
uint64_t get_pc() override { return arch.reg.PC; }
|
||||||
|
|
||||||
uint64_t get_next_pc() override { return arch.reg.NEXT_PC; };
|
uint64_t get_next_pc() override { return arch.reg.NEXT_PC; }
|
||||||
|
|
||||||
uint64_t get_instr_word() override { return arch.reg.instruction; }
|
uint64_t get_instr_word() override { return arch.reg.instruction; }
|
||||||
|
|
||||||
@@ -343,9 +365,11 @@ protected:
|
|||||||
|
|
||||||
uint64_t get_total_cycles() override { return arch.reg.icount + arch.cycle_offset; }
|
uint64_t get_total_cycles() override { return arch.reg.icount + arch.cycle_offset; }
|
||||||
|
|
||||||
void update_last_instr_cycles(unsigned cycles) override { arch.cycle_offset += cycles - 1; };
|
void update_last_instr_cycles(unsigned cycles) override { arch.cycle_offset += cycles - 1; }
|
||||||
|
|
||||||
bool is_branch_taken() override { return arch.reg.last_branch; };
|
bool is_branch_taken() override { return arch.reg.last_branch; }
|
||||||
|
|
||||||
|
unsigned get_reg_num() override { return traits<BASE>::NUM_REGS; }
|
||||||
|
|
||||||
riscv_hart_msu_vp<BASE>& arch;
|
riscv_hart_msu_vp<BASE>& arch;
|
||||||
};
|
};
|
||||||
@@ -414,12 +438,8 @@ protected:
|
|||||||
virtual iss::status read_custom_csr_reg(unsigned addr, reg_t& val) { return iss::status::Err; };
|
virtual iss::status read_custom_csr_reg(unsigned addr, reg_t& val) { return iss::status::Err; };
|
||||||
virtual iss::status write_custom_csr_reg(unsigned addr, reg_t val) { return iss::status::Err; };
|
virtual iss::status write_custom_csr_reg(unsigned addr, reg_t val) { return iss::status::Err; };
|
||||||
|
|
||||||
void register_custom_csr_rd(unsigned addr){
|
void register_custom_csr_rd(unsigned addr) { csr_rd_cb[addr] = &this_class::read_custom_csr_reg; }
|
||||||
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_wr(unsigned addr){
|
|
||||||
csr_wr_cb[addr] = &this_class::write_custom_csr_reg;
|
|
||||||
}
|
|
||||||
|
|
||||||
reg_t mhartid_reg{0x0};
|
reg_t mhartid_reg{0x0};
|
||||||
|
|
||||||
@@ -430,6 +450,7 @@ template <typename BASE>
|
|||||||
riscv_hart_msu_vp<BASE>::riscv_hart_msu_vp()
|
riscv_hart_msu_vp<BASE>::riscv_hart_msu_vp()
|
||||||
: state()
|
: state()
|
||||||
, instr_if(*this) {
|
, instr_if(*this) {
|
||||||
|
this->_has_mmu = true;
|
||||||
// reset values
|
// reset values
|
||||||
csr[misa] = traits<BASE>::MISA_VAL;
|
csr[misa] = traits<BASE>::MISA_VAL;
|
||||||
csr[mvendorid] = 0x669;
|
csr[mvendorid] = 0x669;
|
||||||
@@ -457,32 +478,36 @@ riscv_hart_msu_vp<BASE>::riscv_hart_msu_vp()
|
|||||||
// csr_wr_cb[addr] = &this_class::write_csr_reg;
|
// csr_wr_cb[addr] = &this_class::write_csr_reg;
|
||||||
}
|
}
|
||||||
// common regs
|
// common regs
|
||||||
const std::array<unsigned, 22> addrs{{
|
const std::array<unsigned, 22> addrs{{misa, mvendorid, marchid, mimpid, mepc, mtvec, mscratch, mcause,
|
||||||
misa, mvendorid, marchid, mimpid,
|
mtval, mscratch, sepc, stvec, sscratch, scause, stval, sscratch,
|
||||||
mepc, mtvec, mscratch, mcause, mtval, mscratch,
|
uepc, utvec, uscratch, ucause, utval, uscratch}};
|
||||||
sepc, stvec, sscratch, scause, stval, sscratch,
|
|
||||||
uepc, utvec, uscratch, ucause, utval, uscratch
|
|
||||||
}};
|
|
||||||
for(auto addr : addrs) {
|
for(auto addr : addrs) {
|
||||||
csr_rd_cb[addr] = &this_class::read_csr_reg;
|
csr_rd_cb[addr] = &this_class::read_csr_reg;
|
||||||
csr_wr_cb[addr] = &this_class::write_csr_reg;
|
csr_wr_cb[addr] = &this_class::write_csr_reg;
|
||||||
}
|
}
|
||||||
// special handling & overrides
|
// special handling & overrides
|
||||||
csr_rd_cb[time] = &this_class::read_time;
|
csr_rd_cb[time] = &this_class::read_time;
|
||||||
if(traits<BASE>::XLEN==32) csr_rd_cb[timeh] = &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;
|
csr_rd_cb[cycle] = &this_class::read_cycle;
|
||||||
if(traits<BASE>::XLEN==32) csr_rd_cb[cycleh] = &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;
|
csr_rd_cb[instret] = &this_class::read_instret;
|
||||||
if(traits<BASE>::XLEN==32) csr_rd_cb[instreth] = &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_rd_cb[mcycle] = &this_class::read_cycle;
|
||||||
csr_wr_cb[mcycle] = &this_class::write_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)
|
||||||
if(traits<BASE>::XLEN==32) csr_wr_cb[mcycleh] = &this_class::write_cycle;
|
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_rd_cb[minstret] = &this_class::read_instret;
|
||||||
csr_wr_cb[minstret] = &this_class::write_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)
|
||||||
if(traits<BASE>::XLEN==32) csr_wr_cb[minstreth] = &this_class::write_instret;
|
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_rd_cb[mstatus] = &this_class::read_status;
|
||||||
csr_wr_cb[mstatus] = &this_class::write_status;
|
csr_wr_cb[mstatus] = &this_class::write_status;
|
||||||
csr_wr_cb[mcause] = &this_class::write_cause;
|
csr_wr_cb[mcause] = &this_class::write_cause;
|
||||||
@@ -533,35 +558,37 @@ template <typename BASE> std::pair<uint64_t, bool> riscv_hart_msu_vp<BASE>::load
|
|||||||
std::array<char, 5> buf;
|
std::array<char, 5> buf;
|
||||||
auto n = fread(buf.data(), 1, 4, fp);
|
auto n = fread(buf.data(), 1, 4, fp);
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
if (n != 4) throw std::runtime_error("input file has insufficient size");
|
if(n != 4)
|
||||||
|
throw std::runtime_error("input file has insufficient size");
|
||||||
buf[4] = 0;
|
buf[4] = 0;
|
||||||
if(strcmp(buf.data() + 1, "ELF") == 0) {
|
if(strcmp(buf.data() + 1, "ELF") == 0) {
|
||||||
// Create elfio reader
|
// Create elfio reader
|
||||||
ELFIO::elfio reader;
|
ELFIO::elfio reader;
|
||||||
// Load ELF data
|
// 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
|
// check elf properties
|
||||||
if(reader.get_class() != ELFCLASS32)
|
if(reader.get_class() != ELFCLASS32)
|
||||||
if (sizeof(reg_t) == 4) throw std::runtime_error("wrong elf class in file");
|
if(sizeof(reg_t) == 4)
|
||||||
if (reader.get_type() != ET_EXEC) throw std::runtime_error("wrong elf type in file");
|
throw std::runtime_error("wrong elf class in file");
|
||||||
if (reader.get_machine() != EM_RISCV) throw std::runtime_error("wrong elf machine 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();
|
auto entry = reader.get_entry();
|
||||||
for(const auto pseg : reader.segments) {
|
for(const auto pseg : reader.segments) {
|
||||||
const auto fsize = pseg->get_file_size(); // 0x42c/0x0
|
const auto fsize = pseg->get_file_size(); // 0x42c/0x0
|
||||||
const auto seg_data = pseg->get_data();
|
const auto seg_data = pseg->get_data();
|
||||||
if(fsize > 0) {
|
if(fsize > 0) {
|
||||||
auto res = this->write(iss::address_type::PHYSICAL, iss::access_type::DEBUG_WRITE,
|
auto res = this->write(iss::address_type::PHYSICAL, iss::access_type::DEBUG_WRITE, traits<BASE>::MEM,
|
||||||
traits<BASE>::MEM, pseg->get_physical_address(),
|
pseg->get_physical_address(), fsize, reinterpret_cast<const uint8_t* const>(seg_data));
|
||||||
fsize, reinterpret_cast<const uint8_t *const>(seg_data));
|
|
||||||
if(res != iss::Ok)
|
if(res != iss::Ok)
|
||||||
LOG(ERR) << "problem writing " << fsize << "bytes to 0x" << std::hex
|
LOG(ERR) << "problem writing " << fsize << "bytes to 0x" << std::hex << pseg->get_physical_address();
|
||||||
<< pseg->get_physical_address();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for(const auto sec : reader.sections) {
|
for(const auto sec : reader.sections) {
|
||||||
if(sec->get_name() == ".symtab") {
|
if(sec->get_name() == ".symtab") {
|
||||||
if ( SHT_SYMTAB == sec->get_type() ||
|
if(SHT_SYMTAB == sec->get_type() || SHT_DYNSYM == sec->get_type()) {
|
||||||
SHT_DYNSYM == sec->get_type() ) {
|
|
||||||
ELFIO::symbol_section_accessor symbols(reader, sec);
|
ELFIO::symbol_section_accessor symbols(reader, sec);
|
||||||
auto sym_no = symbols.get_symbols_num();
|
auto sym_no = symbols.get_symbols_num();
|
||||||
std::string name;
|
std::string name;
|
||||||
@@ -584,7 +611,6 @@ template <typename BASE> std::pair<uint64_t, bool> riscv_hart_msu_vp<BASE>::load
|
|||||||
tohost = sec->get_address();
|
tohost = sec->get_address();
|
||||||
fromhost = tohost + 0x40;
|
fromhost = tohost + 0x40;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
return std::make_pair(entry, true);
|
return std::make_pair(entry, true);
|
||||||
}
|
}
|
||||||
@@ -594,8 +620,8 @@ template <typename BASE> std::pair<uint64_t, bool> riscv_hart_msu_vp<BASE>::load
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE>
|
template <typename BASE>
|
||||||
iss::status riscv_hart_msu_vp<BASE>::read(const address_type type, const access_type access, const uint32_t space,
|
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 uint64_t addr, const unsigned length, uint8_t *const data) {
|
const unsigned length, uint8_t* const data) {
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if(access && iss::access_type::DEBUG) {
|
if(access && iss::access_type::DEBUG) {
|
||||||
LOG(TRACEALL) << "debug read of " << length << " bytes @addr 0x" << std::hex << addr;
|
LOG(TRACEALL) << "debug read of " << length << " bytes @addr 0x" << std::hex << addr;
|
||||||
@@ -611,7 +637,8 @@ iss::status riscv_hart_msu_vp<BASE>::read(const address_type type, const access_
|
|||||||
auto alignment = is_fetch(access) ? (traits<BASE>::MISA_VAL & 0x100 ? 2 : 4) : length;
|
auto alignment = is_fetch(access) ? (traits<BASE>::MISA_VAL & 0x100 ? 2 : 4) : length;
|
||||||
if(unlikely(is_fetch(access) && (addr & (alignment - 1)))) {
|
if(unlikely(is_fetch(access) && (addr & (alignment - 1)))) {
|
||||||
fault_data = addr;
|
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
|
this->reg.trap_state = (1 << 31); // issue trap 0
|
||||||
return iss::Err;
|
return iss::Err;
|
||||||
}
|
}
|
||||||
@@ -632,10 +659,8 @@ iss::status riscv_hart_msu_vp<BASE>::read(const address_type type, const access_
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
auto res = type==iss::address_type::PHYSICAL?
|
auto res = read_mem(BASE::v2p(iss::addr_t{access, type, space, addr}), length, data);
|
||||||
read_mem( BASE::v2p(phys_addr_t{access, space, addr}), length, data):
|
if(unlikely(res != iss::Ok && (access & access_type::DEBUG) == 0)) {
|
||||||
read_mem( BASE::v2p(iss::addr_t{access, type, space, addr}), length, data);
|
|
||||||
if (unlikely(res != iss::Ok)){
|
|
||||||
this->reg.trap_state = (1 << 31) | (5 << 16); // issue trap 5 (load access fault
|
this->reg.trap_state = (1 << 31) | (5 << 16); // issue trap 5 (load access fault
|
||||||
fault_data = addr;
|
fault_data = addr;
|
||||||
}
|
}
|
||||||
@@ -647,11 +672,13 @@ iss::status riscv_hart_msu_vp<BASE>::read(const address_type type, const access_
|
|||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case traits<BASE>::CSR: {
|
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));
|
return read_csr(addr, *reinterpret_cast<reg_t* const>(data));
|
||||||
} break;
|
} break;
|
||||||
case traits<BASE>::FENCE: {
|
case traits<BASE>::FENCE: {
|
||||||
if ((addr + length) > mem.size()) return iss::Err;
|
if((addr + length) > mem.size())
|
||||||
|
return iss::Err;
|
||||||
switch(addr) {
|
switch(addr) {
|
||||||
case 2: // SFENCE:VMA lower
|
case 2: // SFENCE:VMA lower
|
||||||
case 3: { // SFENCE:VMA upper
|
case 3: { // SFENCE:VMA upper
|
||||||
@@ -685,26 +712,26 @@ iss::status riscv_hart_msu_vp<BASE>::read(const address_type type, const access_
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE>
|
template <typename BASE>
|
||||||
iss::status riscv_hart_msu_vp<BASE>::write(const address_type type, const access_type access, const uint32_t space,
|
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 uint64_t addr, const unsigned length, const uint8_t *const data) {
|
const unsigned length, const uint8_t* const data) {
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
const char* prefix = (access && iss::access_type::DEBUG) ? "debug " : "";
|
const char* prefix = (access && iss::access_type::DEBUG) ? "debug " : "";
|
||||||
switch(length) {
|
switch(length) {
|
||||||
case 8:
|
case 8:
|
||||||
LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint64_t *)&data[0] << std::dec
|
LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint64_t*)&data[0] << std::dec << ") @addr 0x"
|
||||||
<< ") @addr 0x" << std::hex << addr;
|
<< std::hex << addr;
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint32_t *)&data[0] << std::dec
|
LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint32_t*)&data[0] << std::dec << ") @addr 0x"
|
||||||
<< ") @addr 0x" << std::hex << addr;
|
<< std::hex << addr;
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint16_t *)&data[0] << std::dec
|
LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint16_t*)&data[0] << std::dec << ") @addr 0x"
|
||||||
<< ") @addr 0x" << std::hex << addr;
|
<< std::hex << addr;
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << (uint16_t)data[0] << std::dec
|
LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << (uint16_t)data[0] << std::dec << ") @addr 0x"
|
||||||
<< ") @addr 0x" << std::hex << addr;
|
<< std::hex << addr;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
LOG(TRACE) << prefix << "write of " << length << " bytes @addr " << addr;
|
LOG(TRACE) << prefix << "write of " << length << " bytes @addr " << addr;
|
||||||
@@ -715,10 +742,12 @@ iss::status riscv_hart_msu_vp<BASE>::write(const address_type type, const access
|
|||||||
case traits<BASE>::MEM: {
|
case traits<BASE>::MEM: {
|
||||||
if(unlikely((access && iss::access_type::FETCH) && (addr & 0x1) == 1)) {
|
if(unlikely((access && iss::access_type::FETCH) && (addr & 0x1) == 1)) {
|
||||||
fault_data = addr;
|
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
|
this->reg.trap_state = (1 << 31); // issue trap 0
|
||||||
return iss::Err;
|
return iss::Err;
|
||||||
}
|
}
|
||||||
|
phys_addr_t paddr = BASE::v2p(iss::addr_t{access, type, space, addr});
|
||||||
try {
|
try {
|
||||||
if(unlikely((addr & ~PGMASK) != ((addr + length - 1) & ~PGMASK))) { // we may cross a page boundary
|
if(unlikely((addr & ~PGMASK) != ((addr + length - 1) & ~PGMASK))) { // we may cross a page boundary
|
||||||
vm_info vm = hart_state_type::decode_vm_info(this->reg.PRIV, state.satp);
|
vm_info vm = hart_state_type::decode_vm_info(this->reg.PRIV, state.satp);
|
||||||
@@ -731,10 +760,8 @@ iss::status riscv_hart_msu_vp<BASE>::write(const address_type type, const access
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
auto res = type==iss::address_type::PHYSICAL?
|
auto res = write_mem(paddr, length, data);
|
||||||
write_mem(phys_addr_t{access, space, addr}, length, data):
|
if(unlikely(res != iss::Ok && (access & access_type::DEBUG) == 0)) {
|
||||||
write_mem(BASE::v2p(iss::addr_t{access, type, space, addr}), length, data);
|
|
||||||
if (unlikely(res != iss::Ok)) {
|
|
||||||
this->reg.trap_state = (1UL << 31) | (7UL << 16); // issue trap 7 (Store/AMO access fault)
|
this->reg.trap_state = (1UL << 31) | (7UL << 16); // issue trap 7 (Store/AMO access fault)
|
||||||
fault_data = addr;
|
fault_data = addr;
|
||||||
}
|
}
|
||||||
@@ -745,8 +772,8 @@ iss::status riscv_hart_msu_vp<BASE>::write(const address_type type, const access
|
|||||||
return iss::Err;
|
return iss::Err;
|
||||||
}
|
}
|
||||||
|
|
||||||
phys_addr_t paddr = BASE::v2p(iss::addr_t{access, type, space, addr});
|
if((paddr.val + length) > mem.size())
|
||||||
if ((paddr.val + length) > mem.size()) return iss::Err;
|
return iss::Err;
|
||||||
switch(paddr.val) {
|
switch(paddr.val) {
|
||||||
case 0x10013000: // UART0 base, TXFIFO reg
|
case 0x10013000: // UART0 base, TXFIFO reg
|
||||||
case 0x10023000: // UART1 base, TXFIFO reg
|
case 0x10023000: // UART1 base, TXFIFO reg
|
||||||
@@ -763,7 +790,8 @@ iss::status riscv_hart_msu_vp<BASE>::write(const address_type type, const access
|
|||||||
auto offs = paddr.val & mem.page_addr_mask;
|
auto offs = paddr.val & mem.page_addr_mask;
|
||||||
std::copy(data, data + length, p.data() + offs);
|
std::copy(data, data + length, p.data() + offs);
|
||||||
auto& x = *(p.data() + offs + 3);
|
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;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
case 0x10008008: { // HFROSC base, pllcfg reg
|
case 0x10008008: { // HFROSC base, pllcfg reg
|
||||||
@@ -778,11 +806,13 @@ iss::status riscv_hart_msu_vp<BASE>::write(const address_type type, const access
|
|||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case traits<BASE>::CSR: {
|
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));
|
return write_csr(addr, *reinterpret_cast<const reg_t*>(data));
|
||||||
} break;
|
} break;
|
||||||
case traits<BASE>::FENCE: {
|
case traits<BASE>::FENCE: {
|
||||||
if ((addr + length) > mem.size()) return iss::Err;
|
if((addr + length) > mem.size())
|
||||||
|
return iss::Err;
|
||||||
switch(addr) {
|
switch(addr) {
|
||||||
case 2:
|
case 2:
|
||||||
case 3: {
|
case 3: {
|
||||||
@@ -812,7 +842,8 @@ iss::status riscv_hart_msu_vp<BASE>::write(const address_type type, const access
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::read_csr(unsigned addr, reg_t& val) {
|
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;
|
auto req_priv_lvl = (addr >> 8) & 0x3;
|
||||||
if(this->reg.PRIV < req_priv_lvl) // not having required privileges
|
if(this->reg.PRIV < req_priv_lvl) // not having required privileges
|
||||||
throw illegal_instruction_fault(this->fault_data);
|
throw illegal_instruction_fault(this->fault_data);
|
||||||
@@ -823,7 +854,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) {
|
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;
|
auto req_priv_lvl = (addr >> 8) & 0x3;
|
||||||
if(this->reg.PRIV < req_priv_lvl) // not having required privileges
|
if(this->reg.PRIV < req_priv_lvl) // not having required privileges
|
||||||
throw illegal_instruction_fault(this->fault_data);
|
throw illegal_instruction_fault(this->fault_data);
|
||||||
@@ -855,7 +887,8 @@ template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::read_cycle(unsigne
|
|||||||
if(addr == mcycle) {
|
if(addr == mcycle) {
|
||||||
val = static_cast<reg_t>(cycle_val);
|
val = static_cast<reg_t>(cycle_val);
|
||||||
} else if(addr == mcycleh) {
|
} 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);
|
val = static_cast<reg_t>(cycle_val >> 32);
|
||||||
}
|
}
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
@@ -903,7 +936,8 @@ template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::read_time(unsigned
|
|||||||
if(addr == time) {
|
if(addr == time) {
|
||||||
val = static_cast<reg_t>(time_val);
|
val = static_cast<reg_t>(time_val);
|
||||||
} else if(addr == timeh) {
|
} 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);
|
val = static_cast<reg_t>(time_val >> 32);
|
||||||
}
|
}
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
@@ -935,8 +969,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) {
|
template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::read_ie(unsigned addr, reg_t& val) {
|
||||||
val = csr[mie];
|
val = csr[mie];
|
||||||
if (addr < mie) val &= csr[mideleg];
|
if(addr < mie)
|
||||||
if (addr < sie) val &= csr[sideleg];
|
val &= csr[mideleg];
|
||||||
|
if(addr < sie)
|
||||||
|
val &= csr[sideleg];
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -955,8 +991,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) {
|
template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::read_ip(unsigned addr, reg_t& val) {
|
||||||
val = csr[mip];
|
val = csr[mip];
|
||||||
if (addr < mip) val &= csr[mideleg];
|
if(addr < mip)
|
||||||
if (addr < sip) val &= csr[sideleg];
|
val &= csr[mideleg];
|
||||||
|
if(addr < sip)
|
||||||
|
val &= csr[sideleg];
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1021,8 +1059,7 @@ template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::write_fcsr(unsigne
|
|||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE>
|
template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::read_mem(phys_addr_t paddr, unsigned length, uint8_t* const data) {
|
||||||
iss::status riscv_hart_msu_vp<BASE>::read_mem(phys_addr_t paddr, unsigned length, uint8_t *const data) {
|
|
||||||
switch(paddr.val) {
|
switch(paddr.val) {
|
||||||
default: {
|
default: {
|
||||||
for(auto offs = 0U; offs < length; ++offs) {
|
for(auto offs = 0U; offs < length; ++offs) {
|
||||||
@@ -1033,8 +1070,7 @@ iss::status riscv_hart_msu_vp<BASE>::read_mem(phys_addr_t paddr, unsigned length
|
|||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE>
|
template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::write_mem(phys_addr_t paddr, unsigned length, const uint8_t* const data) {
|
||||||
iss::status riscv_hart_msu_vp<BASE>::write_mem(phys_addr_t paddr, unsigned length, const uint8_t *const data) {
|
|
||||||
switch(paddr.val) {
|
switch(paddr.val) {
|
||||||
case 0xFFFF0000: // UART0 base, TXFIFO reg
|
case 0xFFFF0000: // UART0 base, TXFIFO reg
|
||||||
if(((char)data[0]) == '\n' || data[0] == 0) {
|
if(((char)data[0]) == '\n' || data[0] == 0) {
|
||||||
@@ -1048,10 +1084,9 @@ iss::status riscv_hart_msu_vp<BASE>::write_mem(phys_addr_t paddr, unsigned lengt
|
|||||||
std::copy(data, data + length, p.data() + (paddr.val & mem.page_addr_mask));
|
std::copy(data, data + length, p.data() + (paddr.val & mem.page_addr_mask));
|
||||||
// tohost handling in case of riscv-test
|
// tohost handling in case of riscv-test
|
||||||
if(paddr.access && iss::access_type::FUNC) {
|
if(paddr.access && iss::access_type::FUNC) {
|
||||||
auto tohost_upper = (traits<BASE>::XLEN == 32 && paddr.val == (tohost + 4)) ||
|
auto tohost_upper =
|
||||||
(traits<BASE>::XLEN == 64 && paddr.val == tohost);
|
(traits<BASE>::XLEN == 32 && paddr.val == (tohost + 4)) || (traits<BASE>::XLEN == 64 && paddr.val == tohost);
|
||||||
auto tohost_lower =
|
auto tohost_lower = (traits<BASE>::XLEN == 32 && paddr.val == tohost) || (traits<BASE>::XLEN == 64 && paddr.val == tohost);
|
||||||
(traits<BASE>::XLEN == 32 && paddr.val == tohost) || (traits<BASE>::XLEN == 64 && paddr.val == tohost);
|
|
||||||
if(tohost_lower || tohost_upper) {
|
if(tohost_lower || tohost_upper) {
|
||||||
uint64_t hostvar = *reinterpret_cast<uint64_t*>(p.data() + (tohost & mem.page_addr_mask));
|
uint64_t hostvar = *reinterpret_cast<uint64_t*>(p.data() + (tohost & mem.page_addr_mask));
|
||||||
if(tohost_upper || (tohost_lower && to_host_wr_cnt > 0)) {
|
if(tohost_upper || (tohost_lower && to_host_wr_cnt > 0)) {
|
||||||
@@ -1082,8 +1117,7 @@ iss::status riscv_hart_msu_vp<BASE>::write_mem(phys_addr_t paddr, unsigned lengt
|
|||||||
}
|
}
|
||||||
} else if(tohost_lower)
|
} else if(tohost_lower)
|
||||||
to_host_wr_cnt++;
|
to_host_wr_cnt++;
|
||||||
} else if ((traits<BASE>::XLEN == 32 && paddr.val == fromhost + 4) ||
|
} else if((traits<BASE>::XLEN == 32 && paddr.val == fromhost + 4) || (traits<BASE>::XLEN == 64 && paddr.val == fromhost)) {
|
||||||
(traits<BASE>::XLEN == 64 && paddr.val == fromhost)) {
|
|
||||||
uint64_t fhostvar = *reinterpret_cast<uint64_t*>(p.data() + (fromhost & mem.page_addr_mask));
|
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;
|
*reinterpret_cast<uint64_t*>(p.data() + (tohost & mem.page_addr_mask)) = fhostvar;
|
||||||
}
|
}
|
||||||
@@ -1132,13 +1166,13 @@ template <typename BASE> void riscv_hart_msu_vp<BASE>::check_interrupt() {
|
|||||||
}
|
}
|
||||||
if(enabled_interrupts != 0) {
|
if(enabled_interrupts != 0) {
|
||||||
int res = 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
|
this->reg.pending_trap = res << 16 | 1; // 0x80 << 24 | (cause << 16) | trap_id
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE>
|
template <typename BASE> typename riscv_hart_msu_vp<BASE>::phys_addr_t riscv_hart_msu_vp<BASE>::virt2phys(const iss::addr_t& addr) {
|
||||||
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;
|
const auto type = addr.access & iss::access_type::FUNC;
|
||||||
auto it = ptw.find(addr.val >> PGSHIFT);
|
auto it = ptw.find(addr.val >> PGSHIFT);
|
||||||
if(it != ptw.end()) {
|
if(it != ptw.end()) {
|
||||||
@@ -1157,8 +1191,8 @@ typename riscv_hart_msu_vp<BASE>::phys_addr_t riscv_hart_msu_vp<BASE>::virt2phys
|
|||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
uint32_t mode = type != iss::access_type::FETCH && state.mstatus.MPRV ? // MPRV
|
uint32_t mode = type != iss::access_type::FETCH && state.mstatus.MPRV ? // MPRV
|
||||||
state.mstatus.MPP :
|
state.mstatus.MPP
|
||||||
this->reg.PRIV;
|
: this->reg.PRIV;
|
||||||
|
|
||||||
const vm_info& vm = this->vm[static_cast<uint16_t>(type) / 2];
|
const vm_info& vm = this->vm[static_cast<uint16_t>(type) / 2];
|
||||||
|
|
||||||
@@ -1179,9 +1213,10 @@ typename riscv_hart_msu_vp<BASE>::phys_addr_t riscv_hart_msu_vp<BASE>::virt2phys
|
|||||||
|
|
||||||
// check that physical address of PTE is legal
|
// check that physical address of PTE is legal
|
||||||
reg_t pte = 0;
|
reg_t pte = 0;
|
||||||
const uint8_t res = this->read(iss::address_type::PHYSICAL, addr.access,
|
const uint8_t res = this->read(iss::address_type::PHYSICAL, addr.access, traits<BASE>::MEM, base + idx * vm.ptesize, vm.ptesize,
|
||||||
traits<BASE>::MEM, base + idx * vm.ptesize, vm.ptesize, (uint8_t *)&pte);
|
(uint8_t*)&pte);
|
||||||
if (res != 0) throw trap_load_access_fault(addr.val);
|
if(res != 0)
|
||||||
|
throw trap_load_access_fault(addr.val);
|
||||||
const reg_t ppn = pte >> PTE_PPN_SHIFT;
|
const reg_t ppn = pte >> PTE_PPN_SHIFT;
|
||||||
|
|
||||||
if(PTE_TABLE(pte)) { // next level of page table
|
if(PTE_TABLE(pte)) { // next level of page table
|
||||||
@@ -1190,8 +1225,7 @@ typename riscv_hart_msu_vp<BASE>::phys_addr_t riscv_hart_msu_vp<BASE>::virt2phys
|
|||||||
break;
|
break;
|
||||||
} else if(!(pte & PTE_V) || (!(pte & PTE_R) && (pte & PTE_W))) {
|
} else if(!(pte & PTE_V) || (!(pte & PTE_R) && (pte & PTE_W))) {
|
||||||
break;
|
break;
|
||||||
} else if (type == iss::access_type::FETCH
|
} else if(type == iss::access_type::FETCH ? !(pte & PTE_X)
|
||||||
? !(pte & PTE_X)
|
|
||||||
: type == iss::access_type::READ ? !(pte & PTE_R) && !(mxr && (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;
|
break;
|
||||||
@@ -1204,7 +1238,8 @@ typename riscv_hart_msu_vp<BASE>::phys_addr_t riscv_hart_msu_vp<BASE>::virt2phys
|
|||||||
*(uint32_t*)ppte |= ad;
|
*(uint32_t*)ppte |= ad;
|
||||||
#else
|
#else
|
||||||
// take exception if access or possibly dirty bit is not set.
|
// take exception if access or possibly dirty bit is not set.
|
||||||
if ((pte & ad) != ad) break;
|
if((pte & ad) != ad)
|
||||||
|
break;
|
||||||
#endif
|
#endif
|
||||||
// for superpage mappings, make a fake leaf PTE for the TLB's benefit.
|
// for superpage mappings, make a fake leaf PTE for the TLB's benefit.
|
||||||
const reg_t vpn = addr.val >> PGSHIFT;
|
const reg_t vpn = addr.val >> PGSHIFT;
|
||||||
@@ -1234,10 +1269,12 @@ template <typename BASE> uint64_t riscv_hart_msu_vp<BASE>::enter_trap(uint64_t f
|
|||||||
auto cur_priv = this->reg.PRIV;
|
auto cur_priv = this->reg.PRIV;
|
||||||
// flags are ACTIVE[31:31], CAUSE[30:16], TRAPID[15:0]
|
// flags are ACTIVE[31:31], CAUSE[30:16], TRAPID[15:0]
|
||||||
// calculate and write mcause val
|
// calculate and write mcause val
|
||||||
if(flags==std::numeric_limits<uint64_t>::max()) flags=this->reg.trap_state;
|
if(flags == std::numeric_limits<uint64_t>::max())
|
||||||
|
flags = this->reg.trap_state;
|
||||||
auto trap_id = bit_sub<0, 16>(flags);
|
auto trap_id = bit_sub<0, 16>(flags);
|
||||||
auto cause = bit_sub<16, 15>(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
|
// calculate effective privilege level
|
||||||
auto new_priv = PRIV_M;
|
auto new_priv = PRIV_M;
|
||||||
if(trap_id == 0) { // exception
|
if(trap_id == 0) { // exception
|
||||||
@@ -1313,14 +1350,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
|
// calculate addr// set NEXT_PC to trap addressess to jump to based on MODE
|
||||||
// bits in mtvec
|
// bits in mtvec
|
||||||
this->reg.NEXT_PC = ivec & ~0x3UL;
|
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;
|
std::array<char, 32> buffer;
|
||||||
sprintf(buffer.data(), "0x%016lx", addr);
|
sprintf(buffer.data(), "0x%016lx", addr);
|
||||||
if((flags & 0xffffffff) != 0xffffffff)
|
if((flags & 0xffffffff) != 0xffffffff)
|
||||||
CLOG(INFO, disass) << (trap_id ? "Interrupt" : "Trap") << " with cause '"
|
CLOG(INFO, disass) << (trap_id ? "Interrupt" : "Trap") << " with cause '" << (trap_id ? irq_str[cause] : trap_str[cause]) << "' ("
|
||||||
<< (trap_id ? irq_str[cause] : trap_str[cause]) << "' (" << cause << ")"
|
<< cause << ")"
|
||||||
<< " at address " << buffer.data() << " occurred, changing privilege level from "
|
<< " at address " << buffer.data() << " occurred, changing privilege level from " << lvl[cur_priv] << " to "
|
||||||
<< lvl[cur_priv] << " to " << lvl[new_priv];
|
<< lvl[new_priv];
|
||||||
// reset trap state
|
// reset trap state
|
||||||
this->reg.PRIV = new_priv;
|
this->reg.PRIV = new_priv;
|
||||||
this->reg.trap_state = 0;
|
this->reg.trap_state = 0;
|
||||||
@@ -1363,8 +1401,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.
|
// sets the pc to the value stored in the x epc register.
|
||||||
this->reg.NEXT_PC = csr[uepc | inst_priv << 8];
|
this->reg.NEXT_PC = csr[uepc | inst_priv << 8];
|
||||||
CLOG(INFO, disass) << "Executing xRET , changing privilege level from " << lvl[cur_priv] << " to "
|
CLOG(INFO, disass) << "Executing xRET , changing privilege level from " << lvl[cur_priv] << " to " << lvl[this->reg.PRIV];
|
||||||
<< lvl[this->reg.PRIV];
|
|
||||||
update_vm_info();
|
update_vm_info();
|
||||||
check_interrupt();
|
check_interrupt();
|
||||||
return this->reg.NEXT_PC;
|
return this->reg.NEXT_PC;
|
||||||
@@ -1378,7 +1415,7 @@ template <typename BASE> void riscv_hart_msu_vp<BASE>::wait_until(uint64_t flags
|
|||||||
this->fault_data = this->reg.PC;
|
this->fault_data = this->reg.PC;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} // namespace arch
|
||||||
}
|
} // namespace iss
|
||||||
|
|
||||||
#endif /* _RISCV_HART_MSU_VP_H */
|
#endif /* _RISCV_HART_MSU_VP_H */
|
||||||
|
|||||||
@@ -35,22 +35,22 @@
|
|||||||
#ifndef _RISCV_HART_MU_P_H
|
#ifndef _RISCV_HART_MU_P_H
|
||||||
#define _RISCV_HART_MU_P_H
|
#define _RISCV_HART_MU_P_H
|
||||||
|
|
||||||
#include "riscv_hart_common.h"
|
|
||||||
#include "iss/arch/traits.h"
|
#include "iss/arch/traits.h"
|
||||||
#include "iss/instrumentation_if.h"
|
#include "iss/instrumentation_if.h"
|
||||||
#include "iss/log_categories.h"
|
#include "iss/log_categories.h"
|
||||||
#include "iss/vm_if.h"
|
#include "iss/vm_if.h"
|
||||||
|
#include "riscv_hart_common.h"
|
||||||
#ifndef FMT_HEADER_ONLY
|
#ifndef FMT_HEADER_ONLY
|
||||||
#define FMT_HEADER_ONLY
|
#define FMT_HEADER_ONLY
|
||||||
#endif
|
#endif
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <elfio/elfio.hpp>
|
#include <elfio/elfio.hpp>
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
|
#include <functional>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <functional>
|
|
||||||
#include <util/bit_field.h>
|
#include <util/bit_field.h>
|
||||||
#include <util/ities.h>
|
#include <util/ities.h>
|
||||||
#include <util/sparse_array.h>
|
#include <util/sparse_array.h>
|
||||||
@@ -86,10 +86,11 @@ protected:
|
|||||||
"Load page fault", // d
|
"Load page fault", // d
|
||||||
"Reserved", // e
|
"Reserved", // e
|
||||||
"Store/AMO page fault"}};
|
"Store/AMO page fault"}};
|
||||||
const std::array<const char *, 12> irq_str = {
|
const std::array<const char*, 12> irq_str = {{"User software interrupt", "Supervisor software interrupt", "Reserved",
|
||||||
{"User software interrupt", "Supervisor software interrupt", "Reserved", "Machine software interrupt",
|
"Machine software interrupt", "User timer interrupt", "Supervisor timer interrupt",
|
||||||
"User timer interrupt", "Supervisor timer interrupt", "Reserved", "Machine timer interrupt",
|
"Reserved", "Machine timer interrupt", "User external interrupt",
|
||||||
"User external interrupt", "Supervisor external interrupt", "Reserved", "Machine external interrupt"}};
|
"Supervisor external interrupt", "Reserved", "Machine external interrupt"}};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using core = BASE;
|
using core = BASE;
|
||||||
using this_class = riscv_hart_mu_p<BASE, FEAT>;
|
using this_class = riscv_hart_mu_p<BASE, FEAT>;
|
||||||
@@ -108,7 +109,8 @@ public:
|
|||||||
template <typename T> class hart_state<T, typename std::enable_if<std::is_same<T, uint32_t>::value>::type> {
|
template <typename T> class hart_state<T, typename std::enable_if<std::is_same<T, uint32_t>::value>::type> {
|
||||||
public:
|
public:
|
||||||
BEGIN_BF_DECL(mstatus_t, T);
|
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);
|
BF_FIELD(SD, 31, 1);
|
||||||
// Trap SRET
|
// Trap SRET
|
||||||
BF_FIELD(TSR, 22, 1);
|
BF_FIELD(TSR, 22, 1);
|
||||||
@@ -122,7 +124,8 @@ public:
|
|||||||
BF_FIELD(SUM, 18, 1);
|
BF_FIELD(SUM, 18, 1);
|
||||||
// Modify PRiVilege
|
// Modify PRiVilege
|
||||||
BF_FIELD(MPRV, 17, 1);
|
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);
|
BF_FIELD(XS, 15, 2);
|
||||||
// floating-point unit status Off/Initial/Clean/Dirty
|
// floating-point unit status Off/Initial/Clean/Dirty
|
||||||
BF_FIELD(FS, 13, 2);
|
BF_FIELD(FS, 13, 2);
|
||||||
@@ -159,7 +162,8 @@ public:
|
|||||||
return priv_lvl == PRIV_U ? 0x80000011UL : priv_lvl == PRIV_S ? 0x800de133UL : 0x807ff9ddUL;
|
return priv_lvl == PRIV_U ? 0x80000011UL : priv_lvl == PRIV_S ? 0x800de133UL : 0x807ff9ddUL;
|
||||||
#else
|
#else
|
||||||
switch(priv_lvl) {
|
switch(priv_lvl) {
|
||||||
case PRIV_U: return 0x00000011UL; // 0b1000 0000 0000 0000 0000 0000 0001 0001
|
case PRIV_U:
|
||||||
|
return 0x00000011UL; // 0b1000 0000 0000 0000 0000 0000 0001 0001
|
||||||
default:
|
default:
|
||||||
// +-SD
|
// +-SD
|
||||||
// | +-TSR
|
// | +-TSR
|
||||||
@@ -186,7 +190,8 @@ public:
|
|||||||
template <typename T> class hart_state<T, typename std::enable_if<std::is_same<T, uint64_t>::value>::type> {
|
template <typename T> class hart_state<T, typename std::enable_if<std::is_same<T, uint64_t>::value>::type> {
|
||||||
public:
|
public:
|
||||||
BEGIN_BF_DECL(mstatus_t, T);
|
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);
|
BF_FIELD(SD, 63, 1);
|
||||||
// value of XLEN for S-mode
|
// value of XLEN for S-mode
|
||||||
BF_FIELD(SXL, 34, 2);
|
BF_FIELD(SXL, 34, 2);
|
||||||
@@ -204,7 +209,8 @@ public:
|
|||||||
BF_FIELD(SUM, 18, 1);
|
BF_FIELD(SUM, 18, 1);
|
||||||
// Modify PRiVilege
|
// Modify PRiVilege
|
||||||
BF_FIELD(MPRV, 17, 1);
|
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);
|
BF_FIELD(XS, 15, 2);
|
||||||
// floating-point unit status Off/Initial/Clean/Dirty
|
// floating-point unit status Off/Initial/Clean/Dirty
|
||||||
BF_FIELD(FS, 13, 2);
|
BF_FIELD(FS, 13, 2);
|
||||||
@@ -241,7 +247,8 @@ public:
|
|||||||
return priv_lvl == PRIV_U ? 0x011ULL : priv_lvl == PRIV_S ? 0x000de133ULL : 0x007ff9ddULL;
|
return priv_lvl == PRIV_U ? 0x011ULL : priv_lvl == PRIV_S ? 0x000de133ULL : 0x007ff9ddULL;
|
||||||
#else
|
#else
|
||||||
switch(priv_lvl) {
|
switch(priv_lvl) {
|
||||||
case PRIV_U: return 0x00000011UL; // 0b1000 0000 0000 0000 0000 0000 0001 0001
|
case PRIV_U:
|
||||||
|
return 0x00000011UL; // 0b1000 0000 0000 0000 0000 0000 0001 0001
|
||||||
default:
|
default:
|
||||||
// +-SD
|
// +-SD
|
||||||
// | +-TSR
|
// | +-TSR
|
||||||
@@ -276,12 +283,8 @@ public:
|
|||||||
return m[mode];
|
return m[mode];
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr bool has_compressed() {
|
constexpr bool has_compressed() { return traits<BASE>::MISA_VAL & 0b0100; }
|
||||||
return traits<BASE>::MISA_VAL&0b0100;
|
constexpr reg_t get_pc_mask() { return has_compressed() ? ~1 : ~3; }
|
||||||
}
|
|
||||||
constexpr reg_t get_pc_mask() {
|
|
||||||
return has_compressed()?~1:~3;
|
|
||||||
}
|
|
||||||
|
|
||||||
riscv_hart_mu_p(feature_config cfg = feature_config{});
|
riscv_hart_mu_p(feature_config cfg = feature_config{});
|
||||||
|
|
||||||
@@ -291,10 +294,10 @@ public:
|
|||||||
|
|
||||||
std::pair<uint64_t, bool> load_file(std::string name, int type = -1) override;
|
std::pair<uint64_t, bool> load_file(std::string name, int type = -1) override;
|
||||||
|
|
||||||
iss::status read(const address_type type, const access_type access, const uint32_t space,
|
iss::status read(const address_type type, const access_type access, const uint32_t space, const uint64_t addr, const unsigned length,
|
||||||
const uint64_t addr, const unsigned length, uint8_t *const data) override;
|
uint8_t* const data) override;
|
||||||
iss::status write(const address_type type, const access_type access, const uint32_t space,
|
iss::status write(const address_type type, const access_type access, const uint32_t space, const uint64_t addr, const unsigned length,
|
||||||
const uint64_t addr, const unsigned length, const uint8_t *const data) override;
|
const uint8_t* const data) override;
|
||||||
|
|
||||||
uint64_t enter_trap(uint64_t flags) override { return riscv_hart_mu_p::enter_trap(flags, fault_data, fault_data); }
|
uint64_t enter_trap(uint64_t flags) override { return riscv_hart_mu_p::enter_trap(flags, fault_data, fault_data); }
|
||||||
uint64_t enter_trap(uint64_t flags, uint64_t addr, uint64_t instr) override;
|
uint64_t enter_trap(uint64_t flags, uint64_t addr, uint64_t instr) override;
|
||||||
@@ -304,19 +307,16 @@ public:
|
|||||||
void set_mhartid(reg_t mhartid) { mhartid_reg = mhartid; };
|
void set_mhartid(reg_t mhartid) { mhartid_reg = mhartid; };
|
||||||
|
|
||||||
void disass_output(uint64_t pc, const std::string instr) 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:{}]",
|
CLOG(INFO, disass) << fmt::format("0x{:016x} {:40} [p:{};s:0x{:x};c:{}]", pc, instr, lvl[this->reg.PRIV], (reg_t)state.mstatus,
|
||||||
pc, instr, lvl[this->reg.PRIV], (reg_t)state.mstatus, this->reg.icount + cycle_offset);
|
this->reg.icount + cycle_offset);
|
||||||
};
|
};
|
||||||
|
|
||||||
iss::instrumentation_if* get_instrumentation_if() override { return &instr_if; }
|
iss::instrumentation_if* get_instrumentation_if() override { return &instr_if; }
|
||||||
|
|
||||||
void set_csr(unsigned addr, reg_t val){
|
void set_csr(unsigned addr, reg_t val) { csr[addr & csr.page_addr_mask] = val; }
|
||||||
csr[addr & csr.page_addr_mask] = val;
|
|
||||||
}
|
void set_irq_num(unsigned i) { mcause_max_irq = 1 << util::ilog2(i); }
|
||||||
|
|
||||||
void set_irq_num(unsigned i) {
|
|
||||||
mcause_max_irq=1<<util::ilog2(i);
|
|
||||||
}
|
|
||||||
protected:
|
protected:
|
||||||
struct riscv_instrumentation_if : public iss::instrumentation_if {
|
struct riscv_instrumentation_if : public iss::instrumentation_if {
|
||||||
|
|
||||||
@@ -329,9 +329,9 @@ protected:
|
|||||||
*/
|
*/
|
||||||
const std::string core_type_name() const override { return traits<BASE>::core_type; }
|
const std::string core_type_name() const override { return traits<BASE>::core_type; }
|
||||||
|
|
||||||
uint64_t get_pc() override { return arch.reg.PC; };
|
uint64_t get_pc() override { return arch.reg.PC; }
|
||||||
|
|
||||||
uint64_t get_next_pc() override { return arch.reg.NEXT_PC; };
|
uint64_t get_next_pc() override { return arch.reg.NEXT_PC; }
|
||||||
|
|
||||||
uint64_t get_instr_word() override { return arch.reg.instruction; }
|
uint64_t get_instr_word() override { return arch.reg.instruction; }
|
||||||
|
|
||||||
@@ -341,9 +341,11 @@ protected:
|
|||||||
|
|
||||||
uint64_t get_total_cycles() override { return arch.reg.icount + arch.cycle_offset; }
|
uint64_t get_total_cycles() override { return arch.reg.icount + arch.cycle_offset; }
|
||||||
|
|
||||||
void update_last_instr_cycles(unsigned cycles) override { arch.cycle_offset += cycles - 1; };
|
void update_last_instr_cycles(unsigned cycles) override { arch.cycle_offset += cycles - 1; }
|
||||||
|
|
||||||
bool is_branch_taken() override { return arch.reg.last_branch; };
|
bool is_branch_taken() override { return arch.reg.last_branch; }
|
||||||
|
|
||||||
|
unsigned get_reg_num() override { return traits<BASE>::NUM_REGS; }
|
||||||
|
|
||||||
riscv_hart_mu_p<BASE, FEAT>& arch;
|
riscv_hart_mu_p<BASE, FEAT>& arch;
|
||||||
};
|
};
|
||||||
@@ -431,12 +433,8 @@ protected:
|
|||||||
virtual iss::status read_custom_csr_reg(unsigned addr, reg_t& val) { return iss::status::Err; };
|
virtual iss::status read_custom_csr_reg(unsigned addr, reg_t& val) { return iss::status::Err; };
|
||||||
virtual iss::status write_custom_csr_reg(unsigned addr, reg_t val) { return iss::status::Err; };
|
virtual iss::status write_custom_csr_reg(unsigned addr, reg_t val) { return iss::status::Err; };
|
||||||
|
|
||||||
void register_custom_csr_rd(unsigned addr){
|
void register_custom_csr_rd(unsigned addr) { csr_rd_cb[addr] = &this_class::read_custom_csr_reg; }
|
||||||
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_wr(unsigned addr){
|
|
||||||
csr_wr_cb[addr] = &this_class::write_custom_csr_reg;
|
|
||||||
}
|
|
||||||
|
|
||||||
reg_t mhartid_reg{0x0};
|
reg_t mhartid_reg{0x0};
|
||||||
|
|
||||||
@@ -450,8 +448,8 @@ protected:
|
|||||||
uint64_t mcause_max_irq{(FEAT & features_e::FEAT_CLIC) ? 4096 : 16};
|
uint64_t mcause_max_irq{(FEAT & features_e::FEAT_CLIC) ? 4096 : 16};
|
||||||
inline bool debug_mode_active() { return this->reg.PRIV & 0x4; }
|
inline bool debug_mode_active() { return this->reg.PRIV & 0x4; }
|
||||||
|
|
||||||
std::pair<std::function<mem_read_f>, std::function<mem_write_f>>
|
std::pair<std::function<mem_read_f>, std::function<mem_write_f>> replace_mem_access(std::function<mem_read_f> rd,
|
||||||
replace_mem_access(std::function<mem_read_f> rd, std::function<mem_write_f> wr){
|
std::function<mem_write_f> wr) {
|
||||||
std::pair<std::function<mem_read_f>, std::function<mem_write_f>> ret{hart_mem_rd_delegate, hart_mem_wr_delegate};
|
std::pair<std::function<mem_read_f>, std::function<mem_write_f>> ret{hart_mem_rd_delegate, hart_mem_wr_delegate};
|
||||||
hart_mem_rd_delegate = rd;
|
hart_mem_rd_delegate = rd;
|
||||||
hart_mem_wr_delegate = wr;
|
hart_mem_wr_delegate = wr;
|
||||||
@@ -477,7 +475,8 @@ riscv_hart_mu_p<BASE, FEAT>::riscv_hart_mu_p(feature_config cfg)
|
|||||||
csr_rd_cb[addr] = &this_class::read_null;
|
csr_rd_cb[addr] = &this_class::read_null;
|
||||||
csr_wr_cb[addr] = &this_class::write_csr_reg;
|
csr_wr_cb[addr] = &this_class::write_csr_reg;
|
||||||
}
|
}
|
||||||
if(traits<BASE>::XLEN==32) for (unsigned addr = mhpmcounter3h; addr <= mhpmcounter31h; ++addr){
|
if(traits<BASE>::XLEN == 32)
|
||||||
|
for(unsigned addr = mhpmcounter3h; addr <= mhpmcounter31h; ++addr) {
|
||||||
csr_rd_cb[addr] = &this_class::read_null;
|
csr_rd_cb[addr] = &this_class::read_null;
|
||||||
csr_wr_cb[addr] = &this_class::write_csr_reg;
|
csr_wr_cb[addr] = &this_class::write_csr_reg;
|
||||||
}
|
}
|
||||||
@@ -488,7 +487,8 @@ riscv_hart_mu_p<BASE, FEAT>::riscv_hart_mu_p(feature_config cfg)
|
|||||||
for(unsigned addr = hpmcounter3; addr <= hpmcounter31; ++addr) {
|
for(unsigned addr = hpmcounter3; addr <= hpmcounter31; ++addr) {
|
||||||
csr_rd_cb[addr] = &this_class::read_null;
|
csr_rd_cb[addr] = &this_class::read_null;
|
||||||
}
|
}
|
||||||
if(traits<BASE>::XLEN==32) for (unsigned addr = hpmcounter3h; addr <= hpmcounter31h; ++addr){
|
if(traits<BASE>::XLEN == 32)
|
||||||
|
for(unsigned addr = hpmcounter3h; addr <= hpmcounter31h; ++addr) {
|
||||||
csr_rd_cb[addr] = &this_class::read_null;
|
csr_rd_cb[addr] = &this_class::read_null;
|
||||||
// csr_wr_cb[addr] = &this_class::write_csr_reg;
|
// csr_wr_cb[addr] = &this_class::write_csr_reg;
|
||||||
}
|
}
|
||||||
@@ -499,8 +499,14 @@ riscv_hart_mu_p<BASE, FEAT>::riscv_hart_mu_p(feature_config cfg)
|
|||||||
csr_wr_cb[addr] = &this_class::write_null;
|
csr_wr_cb[addr] = &this_class::write_null;
|
||||||
}
|
}
|
||||||
const std::array<unsigned, 8> rwaddrs{{
|
const std::array<unsigned, 8> rwaddrs{{
|
||||||
mepc, mtvec, mscratch, mtval,
|
mepc,
|
||||||
uepc, utvec, uscratch, utval,
|
mtvec,
|
||||||
|
mscratch,
|
||||||
|
mtval,
|
||||||
|
uepc,
|
||||||
|
utvec,
|
||||||
|
uscratch,
|
||||||
|
utval,
|
||||||
}};
|
}};
|
||||||
for(auto addr : rwaddrs) {
|
for(auto addr : rwaddrs) {
|
||||||
csr_rd_cb[addr] = &this_class::read_csr_reg;
|
csr_rd_cb[addr] = &this_class::read_csr_reg;
|
||||||
@@ -508,20 +514,27 @@ riscv_hart_mu_p<BASE, FEAT>::riscv_hart_mu_p(feature_config cfg)
|
|||||||
}
|
}
|
||||||
// special handling & overrides
|
// special handling & overrides
|
||||||
csr_rd_cb[time] = &this_class::read_time;
|
csr_rd_cb[time] = &this_class::read_time;
|
||||||
if(traits<BASE>::XLEN==32) csr_rd_cb[timeh] = &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;
|
csr_rd_cb[cycle] = &this_class::read_cycle;
|
||||||
if(traits<BASE>::XLEN==32) csr_rd_cb[cycleh] = &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;
|
csr_rd_cb[instret] = &this_class::read_instret;
|
||||||
if(traits<BASE>::XLEN==32) csr_rd_cb[instreth] = &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_rd_cb[mcycle] = &this_class::read_cycle;
|
||||||
csr_wr_cb[mcycle] = &this_class::write_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)
|
||||||
if(traits<BASE>::XLEN==32) csr_wr_cb[mcycleh] = &this_class::write_cycle;
|
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_rd_cb[minstret] = &this_class::read_instret;
|
||||||
csr_wr_cb[minstret] = &this_class::write_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)
|
||||||
if(traits<BASE>::XLEN==32) csr_wr_cb[minstreth] = &this_class::write_instret;
|
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_rd_cb[mstatus] = &this_class::read_status;
|
||||||
csr_wr_cb[mstatus] = &this_class::write_status;
|
csr_wr_cb[mstatus] = &this_class::write_status;
|
||||||
csr_rd_cb[mcause] = &this_class::read_cause;
|
csr_rd_cb[mcause] = &this_class::read_cause;
|
||||||
@@ -593,7 +606,8 @@ riscv_hart_mu_p<BASE, FEAT>::riscv_hart_mu_p(feature_config cfg)
|
|||||||
clic_uact_lvl = clic_uprev_lvl = (1 << (cfg.clic_int_ctl_bits)) - 1;
|
clic_uact_lvl = clic_uprev_lvl = (1 << (cfg.clic_int_ctl_bits)) - 1;
|
||||||
csr[mintthresh] = (1 << (cfg.clic_int_ctl_bits)) - 1;
|
csr[mintthresh] = (1 << (cfg.clic_int_ctl_bits)) - 1;
|
||||||
csr[uintthresh] = (1 << (cfg.clic_int_ctl_bits)) - 1;
|
csr[uintthresh] = (1 << (cfg.clic_int_ctl_bits)) - 1;
|
||||||
insert_mem_range(cfg.clic_base, 0x5000UL,
|
insert_mem_range(
|
||||||
|
cfg.clic_base, 0x5000UL,
|
||||||
[this](phys_addr_t addr, unsigned length, uint8_t* const data) { return read_clic(addr.val, length, data); },
|
[this](phys_addr_t addr, unsigned length, uint8_t* const data) { return read_clic(addr.val, length, data); },
|
||||||
[this](phys_addr_t addr, unsigned length, uint8_t const* const data) { return write_clic(addr.val, length, data); });
|
[this](phys_addr_t addr, unsigned length, uint8_t const* const data) { return write_clic(addr.val, length, data); });
|
||||||
}
|
}
|
||||||
@@ -621,12 +635,8 @@ riscv_hart_mu_p<BASE, FEAT>::riscv_hart_mu_p(feature_config cfg)
|
|||||||
csr_wr_cb[dcsr] = &this_class::write_dcsr_dcsr;
|
csr_wr_cb[dcsr] = &this_class::write_dcsr_dcsr;
|
||||||
csr_rd_cb[dcsr] = &this_class::read_dcsr_reg;
|
csr_rd_cb[dcsr] = &this_class::read_dcsr_reg;
|
||||||
}
|
}
|
||||||
hart_mem_rd_delegate = [this](phys_addr_t a, unsigned l, uint8_t* const d) -> iss::status {
|
hart_mem_rd_delegate = [this](phys_addr_t a, unsigned l, uint8_t* const d) -> iss::status { return this->read_mem(a, l, d); };
|
||||||
return this->read_mem(a, l, d);
|
hart_mem_wr_delegate = [this](phys_addr_t a, unsigned l, uint8_t const* const d) -> iss::status { return this->write_mem(a, l, d); };
|
||||||
};
|
|
||||||
hart_mem_wr_delegate = [this](phys_addr_t a, unsigned l, uint8_t const* const d) -> iss::status {
|
|
||||||
return this->write_mem(a, l, d);
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT> std::pair<uint64_t, bool> riscv_hart_mu_p<BASE, FEAT>::load_file(std::string name, int type) {
|
template <typename BASE, features_e FEAT> std::pair<uint64_t, bool> riscv_hart_mu_p<BASE, FEAT>::load_file(std::string name, int type) {
|
||||||
@@ -635,35 +645,37 @@ template <typename BASE, features_e FEAT> std::pair<uint64_t, bool> riscv_hart_m
|
|||||||
std::array<char, 5> buf;
|
std::array<char, 5> buf;
|
||||||
auto n = fread(buf.data(), 1, 4, fp);
|
auto n = fread(buf.data(), 1, 4, fp);
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
if (n != 4) throw std::runtime_error("input file has insufficient size");
|
if(n != 4)
|
||||||
|
throw std::runtime_error("input file has insufficient size");
|
||||||
buf[4] = 0;
|
buf[4] = 0;
|
||||||
if(strcmp(buf.data() + 1, "ELF") == 0) {
|
if(strcmp(buf.data() + 1, "ELF") == 0) {
|
||||||
// Create elfio reader
|
// Create elfio reader
|
||||||
ELFIO::elfio reader;
|
ELFIO::elfio reader;
|
||||||
// Load ELF data
|
// 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
|
// check elf properties
|
||||||
if(reader.get_class() != ELFCLASS32)
|
if(reader.get_class() != ELFCLASS32)
|
||||||
if (sizeof(reg_t) == 4) throw std::runtime_error("wrong elf class in file");
|
if(sizeof(reg_t) == 4)
|
||||||
if (reader.get_type() != ET_EXEC) throw std::runtime_error("wrong elf type in file");
|
throw std::runtime_error("wrong elf class in file");
|
||||||
if (reader.get_machine() != EM_RISCV) throw std::runtime_error("wrong elf machine 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();
|
auto entry = reader.get_entry();
|
||||||
for(const auto pseg : reader.segments) {
|
for(const auto pseg : reader.segments) {
|
||||||
const auto fsize = pseg->get_file_size(); // 0x42c/0x0
|
const auto fsize = pseg->get_file_size(); // 0x42c/0x0
|
||||||
const auto seg_data = pseg->get_data();
|
const auto seg_data = pseg->get_data();
|
||||||
if(fsize > 0) {
|
if(fsize > 0) {
|
||||||
auto res = this->write(iss::address_type::PHYSICAL, iss::access_type::DEBUG_WRITE,
|
auto res = this->write(iss::address_type::PHYSICAL, iss::access_type::DEBUG_WRITE, traits<BASE>::MEM,
|
||||||
traits<BASE>::MEM, pseg->get_physical_address(),
|
pseg->get_physical_address(), fsize, reinterpret_cast<const uint8_t* const>(seg_data));
|
||||||
fsize, reinterpret_cast<const uint8_t *const>(seg_data));
|
|
||||||
if(res != iss::Ok)
|
if(res != iss::Ok)
|
||||||
LOG(ERR) << "problem writing " << fsize << "bytes to 0x" << std::hex
|
LOG(ERR) << "problem writing " << fsize << "bytes to 0x" << std::hex << pseg->get_physical_address();
|
||||||
<< pseg->get_physical_address();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for(const auto sec : reader.sections) {
|
for(const auto sec : reader.sections) {
|
||||||
if(sec->get_name() == ".symtab") {
|
if(sec->get_name() == ".symtab") {
|
||||||
if ( SHT_SYMTAB == sec->get_type() ||
|
if(SHT_SYMTAB == sec->get_type() || SHT_DYNSYM == sec->get_type()) {
|
||||||
SHT_DYNSYM == sec->get_type() ) {
|
|
||||||
ELFIO::symbol_section_accessor symbols(reader, sec);
|
ELFIO::symbol_section_accessor symbols(reader, sec);
|
||||||
auto sym_no = symbols.get_symbols_num();
|
auto sym_no = symbols.get_symbols_num();
|
||||||
std::string name;
|
std::string name;
|
||||||
@@ -686,7 +698,6 @@ template <typename BASE, features_e FEAT> std::pair<uint64_t, bool> riscv_hart_m
|
|||||||
tohost = sec->get_address();
|
tohost = sec->get_address();
|
||||||
fromhost = tohost + 0x40;
|
fromhost = tohost + 0x40;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
return std::make_pair(entry, true);
|
return std::make_pair(entry, true);
|
||||||
}
|
}
|
||||||
@@ -699,23 +710,22 @@ template<typename BASE, features_e FEAT>
|
|||||||
inline void riscv_hart_mu_p<BASE, FEAT>::insert_mem_range(uint64_t base, uint64_t size, std::function<mem_read_f> rd_f,
|
inline void riscv_hart_mu_p<BASE, FEAT>::insert_mem_range(uint64_t base, uint64_t size, std::function<mem_read_f> rd_f,
|
||||||
std::function<mem_write_f> wr_fn) {
|
std::function<mem_write_f> wr_fn) {
|
||||||
std::tuple<uint64_t, uint64_t> entry{base, size};
|
std::tuple<uint64_t, uint64_t> entry{base, size};
|
||||||
auto it = std::upper_bound( memfn_range.begin(), memfn_range.end(), entry,
|
auto it = std::upper_bound(
|
||||||
[](std::tuple<uint64_t, uint64_t> const& a, std::tuple<uint64_t, uint64_t> const& b){
|
memfn_range.begin(), memfn_range.end(), entry,
|
||||||
return std::get<0>(a)<std::get<0>(b);
|
[](std::tuple<uint64_t, uint64_t> const& a, std::tuple<uint64_t, uint64_t> const& b) { return std::get<0>(a) < std::get<0>(b); });
|
||||||
});
|
|
||||||
auto idx = std::distance(memfn_range.begin(), it);
|
auto idx = std::distance(memfn_range.begin(), it);
|
||||||
memfn_range.insert(it, entry);
|
memfn_range.insert(it, entry);
|
||||||
memfn_read.insert(std::begin(memfn_read) + idx, rd_f);
|
memfn_read.insert(std::begin(memfn_read) + idx, rd_f);
|
||||||
memfn_write.insert(std::begin(memfn_write) + idx, wr_fn);
|
memfn_write.insert(std::begin(memfn_write) + idx, wr_fn);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename BASE, features_e FEAT>
|
template <typename BASE, features_e FEAT> inline iss::status riscv_hart_mu_p<BASE, FEAT>::write_pmpcfg_reg(unsigned addr, reg_t val) {
|
||||||
inline iss::status riscv_hart_mu_p<BASE, FEAT>::write_pmpcfg_reg(unsigned addr, reg_t val) {
|
|
||||||
csr[addr] = val & 0x9f9f9f9f;
|
csr[addr] = val & 0x9f9f9f9f;
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT> bool riscv_hart_mu_p<BASE, FEAT>::pmp_check(const access_type type, const uint64_t addr, const unsigned len) {
|
template <typename BASE, features_e FEAT>
|
||||||
|
bool riscv_hart_mu_p<BASE, FEAT>::pmp_check(const access_type type, const uint64_t addr, const unsigned len) {
|
||||||
constexpr auto PMP_SHIFT = 2U;
|
constexpr auto PMP_SHIFT = 2U;
|
||||||
constexpr auto PMP_R = 0x1U;
|
constexpr auto PMP_R = 0x1U;
|
||||||
constexpr auto PMP_W = 0x2U;
|
constexpr auto PMP_W = 0x2U;
|
||||||
@@ -755,10 +765,8 @@ template <typename BASE, features_e FEAT> bool riscv_hart_mu_p<BASE, FEAT>::pmp_
|
|||||||
// If the PMP matches only a strict subset of the access, fail it
|
// If the PMP matches only a strict subset of the access, fail it
|
||||||
if(!all_match)
|
if(!all_match)
|
||||||
return false;
|
return false;
|
||||||
return (this->reg.PRIV == PRIV_M && !(cfg & PMP_L)) ||
|
return (this->reg.PRIV == PRIV_M && !(cfg & PMP_L)) || (type == access_type::READ && (cfg & PMP_R)) ||
|
||||||
(type == access_type::READ && (cfg & PMP_R)) ||
|
(type == access_type::WRITE && (cfg & PMP_W)) || (type == access_type::FETCH && (cfg & PMP_X));
|
||||||
(type == access_type::WRITE && (cfg & PMP_W)) ||
|
|
||||||
(type == access_type::FETCH && (cfg & PMP_X));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
base = tor;
|
base = tor;
|
||||||
@@ -797,10 +805,9 @@ template <typename BASE, features_e FEAT> bool riscv_hart_mu_p<BASE, FEAT>::pmp_
|
|||||||
return !any_active || this->reg.PRIV == PRIV_M;
|
return !any_active || this->reg.PRIV == PRIV_M;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT>
|
template <typename BASE, features_e FEAT>
|
||||||
iss::status riscv_hart_mu_p<BASE, FEAT>::read(const address_type type, const access_type access, const uint32_t space,
|
iss::status riscv_hart_mu_p<BASE, FEAT>::read(const address_type type, const access_type access, const uint32_t space, const uint64_t addr,
|
||||||
const uint64_t addr, const unsigned length, uint8_t *const data) {
|
const unsigned length, uint8_t* const data) {
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if(access && iss::access_type::DEBUG) {
|
if(access && iss::access_type::DEBUG) {
|
||||||
LOG(TRACEALL) << "debug read of " << length << " bytes @addr 0x" << std::hex << addr;
|
LOG(TRACEALL) << "debug read of " << length << " bytes @addr 0x" << std::hex << addr;
|
||||||
@@ -816,7 +823,8 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::read(const address_type type, const acc
|
|||||||
if(FEAT & FEAT_PMP) {
|
if(FEAT & FEAT_PMP) {
|
||||||
if(!pmp_check(access, addr, length) && !is_debug(access)) {
|
if(!pmp_check(access, addr, length) && !is_debug(access)) {
|
||||||
fault_data = addr;
|
fault_data = addr;
|
||||||
if (is_debug(access)) throw trap_access(0, addr);
|
if(is_debug(access))
|
||||||
|
throw trap_access(0, addr);
|
||||||
this->reg.trap_state = (1UL << 31) | ((access == access_type::FETCH ? 1 : 5) << 16); // issue trap 1
|
this->reg.trap_state = (1UL << 31) | ((access == access_type::FETCH ? 1 : 5) << 16); // issue trap 1
|
||||||
return iss::Err;
|
return iss::Err;
|
||||||
}
|
}
|
||||||
@@ -824,7 +832,8 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::read(const address_type type, const acc
|
|||||||
auto alignment = is_fetch(access) ? (has_compressed() ? 2 : 4) : length;
|
auto alignment = is_fetch(access) ? (has_compressed() ? 2 : 4) : length;
|
||||||
if(unlikely(is_fetch(access) && (addr & (alignment - 1)))) {
|
if(unlikely(is_fetch(access) && (addr & (alignment - 1)))) {
|
||||||
fault_data = addr;
|
fault_data = addr;
|
||||||
if (is_debug(access)) throw trap_access(0, addr);
|
if(is_debug(access))
|
||||||
|
throw trap_access(0, addr);
|
||||||
this->reg.trap_state = (1UL << 31); // issue trap 0
|
this->reg.trap_state = (1UL << 31); // issue trap 0
|
||||||
return iss::Err;
|
return iss::Err;
|
||||||
}
|
}
|
||||||
@@ -834,10 +843,11 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::read(const address_type type, const acc
|
|||||||
fault_data = addr;
|
fault_data = addr;
|
||||||
return iss::Err;
|
return iss::Err;
|
||||||
}
|
}
|
||||||
auto phys_addr = type==iss::address_type::PHYSICAL?phys_addr_t{access, space, addr}:BASE::v2p(iss::addr_t{access, type, space, addr});
|
phys_addr_t phys_addr{access, space, addr};
|
||||||
auto res = iss::Err;
|
auto res = iss::Err;
|
||||||
if(!is_fetch(access) && memfn_range.size()) {
|
if(!is_fetch(access) && memfn_range.size()) {
|
||||||
auto it = std::find_if(std::begin(memfn_range), std::end(memfn_range), [phys_addr](std::tuple<uint64_t, uint64_t> const& a){
|
auto it =
|
||||||
|
std::find_if(std::begin(memfn_range), std::end(memfn_range), [phys_addr](std::tuple<uint64_t, uint64_t> const& a) {
|
||||||
return std::get<0>(a) <= phys_addr.val && (std::get<0>(a) + std::get<1>(a)) > phys_addr.val;
|
return std::get<0>(a) <= phys_addr.val && (std::get<0>(a) + std::get<1>(a)) > phys_addr.val;
|
||||||
});
|
});
|
||||||
if(it != std::end(memfn_range)) {
|
if(it != std::end(memfn_range)) {
|
||||||
@@ -848,7 +858,7 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::read(const address_type type, const acc
|
|||||||
} else {
|
} else {
|
||||||
res = hart_mem_rd_delegate(phys_addr, length, data);
|
res = hart_mem_rd_delegate(phys_addr, length, data);
|
||||||
}
|
}
|
||||||
if (unlikely(res != iss::Ok)){
|
if(unlikely(res != iss::Ok && (access & access_type::DEBUG) == 0)) {
|
||||||
this->reg.trap_state = (1UL << 31) | (5 << 16); // issue trap 5 (load access fault
|
this->reg.trap_state = (1UL << 31) | (5 << 16); // issue trap 5 (load access fault
|
||||||
fault_data = addr;
|
fault_data = addr;
|
||||||
}
|
}
|
||||||
@@ -860,11 +870,13 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::read(const address_type type, const acc
|
|||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case traits<BASE>::CSR: {
|
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));
|
return read_csr(addr, *reinterpret_cast<reg_t* const>(data));
|
||||||
} break;
|
} break;
|
||||||
case traits<BASE>::FENCE: {
|
case traits<BASE>::FENCE: {
|
||||||
if ((addr + length) > mem.size()) return iss::Err;
|
if((addr + length) > mem.size())
|
||||||
|
return iss::Err;
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
} break;
|
} break;
|
||||||
case traits<BASE>::RES: {
|
case traits<BASE>::RES: {
|
||||||
@@ -887,26 +899,26 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::read(const address_type type, const acc
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT>
|
template <typename BASE, features_e FEAT>
|
||||||
iss::status riscv_hart_mu_p<BASE, FEAT>::write(const address_type type, const access_type access, const uint32_t space,
|
iss::status riscv_hart_mu_p<BASE, FEAT>::write(const address_type type, const access_type access, const uint32_t space, const uint64_t addr,
|
||||||
const uint64_t addr, const unsigned length, const uint8_t *const data) {
|
const unsigned length, const uint8_t* const data) {
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
const char* prefix = (access && iss::access_type::DEBUG) ? "debug " : "";
|
const char* prefix = (access && iss::access_type::DEBUG) ? "debug " : "";
|
||||||
switch(length) {
|
switch(length) {
|
||||||
case 8:
|
case 8:
|
||||||
LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint64_t *)&data[0] << std::dec
|
LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint64_t*)&data[0] << std::dec << ") @addr 0x"
|
||||||
<< ") @addr 0x" << std::hex << addr;
|
<< std::hex << addr;
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint32_t *)&data[0] << std::dec
|
LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint32_t*)&data[0] << std::dec << ") @addr 0x"
|
||||||
<< ") @addr 0x" << std::hex << addr;
|
<< std::hex << addr;
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint16_t *)&data[0] << std::dec
|
LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint16_t*)&data[0] << std::dec << ") @addr 0x"
|
||||||
<< ") @addr 0x" << std::hex << addr;
|
<< std::hex << addr;
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << (uint16_t)data[0] << std::dec
|
LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << (uint16_t)data[0] << std::dec << ") @addr 0x"
|
||||||
<< ") @addr 0x" << std::hex << addr;
|
<< std::hex << addr;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
LOG(TRACE) << prefix << "write of " << length << " bytes @addr " << addr;
|
LOG(TRACE) << prefix << "write of " << length << " bytes @addr " << addr;
|
||||||
@@ -918,14 +930,16 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::write(const address_type type, const ac
|
|||||||
if(FEAT & FEAT_PMP) {
|
if(FEAT & FEAT_PMP) {
|
||||||
if(!pmp_check(access, addr, length) && (access & access_type::DEBUG) != access_type::DEBUG) {
|
if(!pmp_check(access, addr, length) && (access & access_type::DEBUG) != access_type::DEBUG) {
|
||||||
fault_data = addr;
|
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 = (1UL << 31) | (7 << 16); // issue trap 1
|
this->reg.trap_state = (1UL << 31) | (7 << 16); // issue trap 1
|
||||||
return iss::Err;
|
return iss::Err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(unlikely(is_fetch(access) && (addr & 0x1) == 1)) {
|
if(unlikely(is_fetch(access) && (addr & 0x1) == 1)) {
|
||||||
fault_data = addr;
|
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 = (1UL << 31); // issue trap 0
|
this->reg.trap_state = (1UL << 31); // issue trap 0
|
||||||
return iss::Err;
|
return iss::Err;
|
||||||
}
|
}
|
||||||
@@ -935,10 +949,11 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::write(const address_type type, const ac
|
|||||||
fault_data = addr;
|
fault_data = addr;
|
||||||
return iss::Err;
|
return iss::Err;
|
||||||
}
|
}
|
||||||
auto phys_addr = type==iss::address_type::PHYSICAL?phys_addr_t{access, space, addr}:BASE::v2p(iss::addr_t{access, type, space, addr});
|
phys_addr_t phys_addr{access, space, addr};
|
||||||
auto res = iss::Err;
|
auto res = iss::Err;
|
||||||
if(!is_fetch(access) && memfn_range.size()) {
|
if(!is_fetch(access) && memfn_range.size()) {
|
||||||
auto it = std::find_if(std::begin(memfn_range), std::end(memfn_range), [phys_addr](std::tuple<uint64_t, uint64_t> const& a){
|
auto it =
|
||||||
|
std::find_if(std::begin(memfn_range), std::end(memfn_range), [phys_addr](std::tuple<uint64_t, uint64_t> const& a) {
|
||||||
return std::get<0>(a) <= phys_addr.val && (std::get<0>(a) + std::get<1>(a)) > phys_addr.val;
|
return std::get<0>(a) <= phys_addr.val && (std::get<0>(a) + std::get<1>(a)) > phys_addr.val;
|
||||||
});
|
});
|
||||||
if(it != std::end(memfn_range)) {
|
if(it != std::end(memfn_range)) {
|
||||||
@@ -949,7 +964,7 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::write(const address_type type, const ac
|
|||||||
} else {
|
} else {
|
||||||
res = hart_mem_wr_delegate(phys_addr, length, data);
|
res = hart_mem_wr_delegate(phys_addr, length, data);
|
||||||
}
|
}
|
||||||
if (unlikely(res != iss::Ok)) {
|
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)
|
this->reg.trap_state = (1UL << 31) | (7UL << 16); // issue trap 7 (Store/AMO access fault)
|
||||||
fault_data = addr;
|
fault_data = addr;
|
||||||
}
|
}
|
||||||
@@ -960,30 +975,31 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::write(const address_type type, const ac
|
|||||||
return iss::Err;
|
return iss::Err;
|
||||||
}
|
}
|
||||||
|
|
||||||
phys_addr_t paddr = BASE::v2p(iss::addr_t{access, type, space, addr});
|
if((addr + length) > mem.size())
|
||||||
if ((paddr.val + length) > mem.size()) return iss::Err;
|
return iss::Err;
|
||||||
switch (paddr.val) {
|
switch(addr) {
|
||||||
case 0x10013000: // UART0 base, TXFIFO reg
|
case 0x10013000: // UART0 base, TXFIFO reg
|
||||||
case 0x10023000: // UART1 base, TXFIFO reg
|
case 0x10023000: // UART1 base, TXFIFO reg
|
||||||
uart_buf << (char)data[0];
|
uart_buf << (char)data[0];
|
||||||
if(((char)data[0]) == '\n' || data[0] == 0) {
|
if(((char)data[0]) == '\n' || data[0] == 0) {
|
||||||
// LOG(INFO)<<"UART"<<((paddr.val>>16)&0x3)<<" send
|
// LOG(INFO)<<"UART"<<((addr>>16)&0x3)<<" send
|
||||||
// '"<<uart_buf.str()<<"'";
|
// '"<<uart_buf.str()<<"'";
|
||||||
std::cout << uart_buf.str();
|
std::cout << uart_buf.str();
|
||||||
uart_buf.str("");
|
uart_buf.str("");
|
||||||
}
|
}
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
case 0x10008000: { // HFROSC base, hfrosccfg reg
|
case 0x10008000: { // HFROSC base, hfrosccfg reg
|
||||||
auto &p = mem(paddr.val / mem.page_size);
|
auto& p = mem(addr / mem.page_size);
|
||||||
auto offs = paddr.val & mem.page_addr_mask;
|
auto offs = addr & mem.page_addr_mask;
|
||||||
std::copy(data, data + length, p.data() + offs);
|
std::copy(data, data + length, p.data() + offs);
|
||||||
auto& x = *(p.data() + offs + 3);
|
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;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
case 0x10008008: { // HFROSC base, pllcfg reg
|
case 0x10008008: { // HFROSC base, pllcfg reg
|
||||||
auto &p = mem(paddr.val / mem.page_size);
|
auto& p = mem(addr / mem.page_size);
|
||||||
auto offs = paddr.val & mem.page_addr_mask;
|
auto offs = addr & mem.page_addr_mask;
|
||||||
std::copy(data, data + length, p.data() + offs);
|
std::copy(data, data + length, p.data() + offs);
|
||||||
auto& x = *(p.data() + offs + 3);
|
auto& x = *(p.data() + offs + 3);
|
||||||
x |= 0x80; // set pll lock upon writing
|
x |= 0x80; // set pll lock upon writing
|
||||||
@@ -993,11 +1009,13 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::write(const address_type type, const ac
|
|||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case traits<BASE>::CSR: {
|
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));
|
return write_csr(addr, *reinterpret_cast<const reg_t*>(data));
|
||||||
} break;
|
} break;
|
||||||
case traits<BASE>::FENCE: {
|
case traits<BASE>::FENCE: {
|
||||||
if ((addr + length) > mem.size()) return iss::Err;
|
if((addr + length) > mem.size())
|
||||||
|
return iss::Err;
|
||||||
switch(addr) {
|
switch(addr) {
|
||||||
case 2:
|
case 2:
|
||||||
case 3: {
|
case 3: {
|
||||||
@@ -1022,7 +1040,8 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::write(const address_type type, const ac
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::read_csr(unsigned addr, reg_t& val) {
|
template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::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;
|
auto req_priv_lvl = (addr >> 8) & 0x3;
|
||||||
if(this->reg.PRIV < req_priv_lvl) // not having required privileges
|
if(this->reg.PRIV < req_priv_lvl) // not having required privileges
|
||||||
throw illegal_instruction_fault(this->fault_data);
|
throw illegal_instruction_fault(this->fault_data);
|
||||||
@@ -1033,7 +1052,8 @@ template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::write_csr(unsigned addr, reg_t val) {
|
template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::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;
|
auto req_priv_lvl = (addr >> 8) & 0x3;
|
||||||
if(this->reg.PRIV < req_priv_lvl) // not having required privileges
|
if(this->reg.PRIV < req_priv_lvl) // not having required privileges
|
||||||
throw illegal_instruction_fault(this->fault_data);
|
throw illegal_instruction_fault(this->fault_data);
|
||||||
@@ -1112,7 +1132,8 @@ template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT
|
|||||||
if(addr == time) {
|
if(addr == time) {
|
||||||
val = static_cast<reg_t>(time_val);
|
val = static_cast<reg_t>(time_val);
|
||||||
} else if(addr == timeh) {
|
} 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);
|
val = static_cast<reg_t>(time_val >> 32);
|
||||||
}
|
}
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
@@ -1260,8 +1281,7 @@ template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT
|
|||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename BASE, features_e FEAT>
|
template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::read_intstatus(unsigned addr, reg_t& val) {
|
||||||
iss::status riscv_hart_mu_p<BASE, FEAT>::read_intstatus(unsigned addr, reg_t& val) {
|
|
||||||
auto mode = (addr >> 8) & 0x3;
|
auto mode = (addr >> 8) & 0x3;
|
||||||
val = clic_uact_lvl & 0xff;
|
val = clic_uact_lvl & 0xff;
|
||||||
if(mode == 0x3)
|
if(mode == 0x3)
|
||||||
@@ -1269,14 +1289,12 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::read_intstatus(unsigned addr, reg_t& va
|
|||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename BASE, features_e FEAT>
|
template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::write_intthresh(unsigned addr, reg_t val) {
|
||||||
iss::status riscv_hart_mu_p<BASE, FEAT>::write_intthresh(unsigned addr, reg_t val) {
|
|
||||||
csr[addr] = (val & 0xff) | (1 << (cfg.clic_int_ctl_bits)) - 1;
|
csr[addr] = (val & 0xff) | (1 << (cfg.clic_int_ctl_bits)) - 1;
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename BASE, features_e FEAT>
|
template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::write_xtvt(unsigned addr, reg_t val) {
|
||||||
iss::status riscv_hart_mu_p<BASE, FEAT>::write_xtvt(unsigned addr, reg_t val) {
|
|
||||||
csr[addr] = val & ~0x3fULL;
|
csr[addr] = val & ~0x3fULL;
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
@@ -1308,10 +1326,9 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::write_mem(phys_addr_t paddr, unsigned l
|
|||||||
std::copy(data, data + length, p.data() + (paddr.val & mem.page_addr_mask));
|
std::copy(data, data + length, p.data() + (paddr.val & mem.page_addr_mask));
|
||||||
// tohost handling in case of riscv-test
|
// tohost handling in case of riscv-test
|
||||||
if(paddr.access && iss::access_type::FUNC) {
|
if(paddr.access && iss::access_type::FUNC) {
|
||||||
auto tohost_upper = (traits<BASE>::XLEN == 32 && paddr.val == (tohost + 4)) ||
|
auto tohost_upper =
|
||||||
(traits<BASE>::XLEN == 64 && paddr.val == tohost);
|
(traits<BASE>::XLEN == 32 && paddr.val == (tohost + 4)) || (traits<BASE>::XLEN == 64 && paddr.val == tohost);
|
||||||
auto tohost_lower =
|
auto tohost_lower = (traits<BASE>::XLEN == 32 && paddr.val == tohost) || (traits<BASE>::XLEN == 64 && paddr.val == tohost);
|
||||||
(traits<BASE>::XLEN == 32 && paddr.val == tohost) || (traits<BASE>::XLEN == 64 && paddr.val == tohost);
|
|
||||||
if(tohost_lower || tohost_upper) {
|
if(tohost_lower || tohost_upper) {
|
||||||
uint64_t hostvar = *reinterpret_cast<uint64_t*>(p.data() + (tohost & mem.page_addr_mask));
|
uint64_t hostvar = *reinterpret_cast<uint64_t*>(p.data() + (tohost & mem.page_addr_mask));
|
||||||
if(tohost_upper || (tohost_lower && to_host_wr_cnt > 0)) {
|
if(tohost_upper || (tohost_lower && to_host_wr_cnt > 0)) {
|
||||||
@@ -1342,8 +1359,7 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::write_mem(phys_addr_t paddr, unsigned l
|
|||||||
}
|
}
|
||||||
} else if(tohost_lower)
|
} else if(tohost_lower)
|
||||||
to_host_wr_cnt++;
|
to_host_wr_cnt++;
|
||||||
} else if ((traits<BASE>::XLEN == 32 && paddr.val == fromhost + 4) ||
|
} else if((traits<BASE>::XLEN == 32 && paddr.val == fromhost + 4) || (traits<BASE>::XLEN == 64 && paddr.val == fromhost)) {
|
||||||
(traits<BASE>::XLEN == 64 && paddr.val == fromhost)) {
|
|
||||||
uint64_t fhostvar = *reinterpret_cast<uint64_t*>(p.data() + (fromhost & mem.page_addr_mask));
|
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;
|
*reinterpret_cast<uint64_t*>(p.data() + (tohost & mem.page_addr_mask)) = fhostvar;
|
||||||
}
|
}
|
||||||
@@ -1357,15 +1373,18 @@ template<typename BASE, features_e FEAT>
|
|||||||
iss::status riscv_hart_mu_p<BASE, FEAT>::read_clic(uint64_t addr, unsigned length, uint8_t* const data) {
|
iss::status riscv_hart_mu_p<BASE, FEAT>::read_clic(uint64_t addr, unsigned length, uint8_t* const data) {
|
||||||
if(addr == cfg.clic_base) { // cliccfg
|
if(addr == cfg.clic_base) { // cliccfg
|
||||||
*data = clic_cfg_reg;
|
*data = clic_cfg_reg;
|
||||||
for(auto i=1; i<length; ++i) *(data+i)=0;
|
for(auto i = 1; i < length; ++i)
|
||||||
|
*(data + i) = 0;
|
||||||
} else if(addr >= (cfg.clic_base + 0x40) && (addr + length) <= (cfg.clic_base + 0x40 + cfg.clic_num_trigger * 4)) { // clicinttrig
|
} else if(addr >= (cfg.clic_base + 0x40) && (addr + length) <= (cfg.clic_base + 0x40 + cfg.clic_num_trigger * 4)) { // clicinttrig
|
||||||
auto offset = ((addr & 0x7fff) - 0x40) / 4;
|
auto offset = ((addr & 0x7fff) - 0x40) / 4;
|
||||||
read_reg_uint32(addr, clic_inttrig_reg[offset], data, length);
|
read_reg_uint32(addr, clic_inttrig_reg[offset], data, length);
|
||||||
} else if(addr>=(cfg.clic_base+0x1000) && (addr+length)<=(cfg.clic_base+0x1000+cfg.clic_num_irq*4)){ // clicintip/clicintie/clicintattr/clicintctl
|
} else if(addr >= (cfg.clic_base + 0x1000) &&
|
||||||
|
(addr + length) <= (cfg.clic_base + 0x1000 + cfg.clic_num_irq * 4)) { // clicintip/clicintie/clicintattr/clicintctl
|
||||||
auto offset = ((addr & 0x7fff) - 0x1000) / 4;
|
auto offset = ((addr & 0x7fff) - 0x1000) / 4;
|
||||||
read_reg_uint32(addr, clic_int_reg[offset].raw, data, length);
|
read_reg_uint32(addr, clic_int_reg[offset].raw, data, length);
|
||||||
} else {
|
} else {
|
||||||
for(auto i = 0U; i<length; ++i) *(data+i)=0;
|
for(auto i = 0U; i < length; ++i)
|
||||||
|
*(data + i) = 0;
|
||||||
}
|
}
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
@@ -1377,7 +1396,8 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::write_clic(uint64_t addr, unsigned leng
|
|||||||
} else if(addr >= (cfg.clic_base + 0x40) && (addr + length) <= (cfg.clic_base + 0x40 + cfg.clic_num_trigger * 4)) { // clicinttrig
|
} else if(addr >= (cfg.clic_base + 0x40) && (addr + length) <= (cfg.clic_base + 0x40 + cfg.clic_num_trigger * 4)) { // clicinttrig
|
||||||
auto offset = ((addr & 0x7fff) - 0x40) / 4;
|
auto offset = ((addr & 0x7fff) - 0x40) / 4;
|
||||||
write_reg_uint32(addr, clic_inttrig_reg[offset], data, length);
|
write_reg_uint32(addr, clic_inttrig_reg[offset], data, length);
|
||||||
} else if(addr>=(cfg.clic_base+0x1000) && (addr+length)<=(cfg.clic_base+0x1000+cfg.clic_num_irq*4)){ // clicintip/clicintie/clicintattr/clicintctl
|
} else if(addr >= (cfg.clic_base + 0x1000) &&
|
||||||
|
(addr + length) <= (cfg.clic_base + 0x1000 + cfg.clic_num_irq * 4)) { // clicintip/clicintie/clicintattr/clicintctl
|
||||||
auto offset = ((addr & 0x7fff) - 0x1000) / 4;
|
auto offset = ((addr & 0x7fff) - 0x1000) / 4;
|
||||||
write_reg_uint32(addr, clic_int_reg[offset].raw, data, length);
|
write_reg_uint32(addr, clic_int_reg[offset].raw, data, length);
|
||||||
clic_int_reg[offset].raw &= 0xf0c70101; // clicIntCtlBits->0xf0, clicintattr->0xc7, clicintie->0x1, clicintip->0x1
|
clic_int_reg[offset].raw &= 0xf0c70101; // clicIntCtlBits->0xf0, clicintattr->0xc7, clicintie->0x1, clicintip->0x1
|
||||||
@@ -1416,10 +1436,12 @@ template <typename BASE, features_e FEAT> void riscv_hart_mu_p<BASE, FEAT>::chec
|
|||||||
template <typename BASE, features_e FEAT> uint64_t riscv_hart_mu_p<BASE, FEAT>::enter_trap(uint64_t flags, uint64_t addr, uint64_t instr) {
|
template <typename BASE, features_e FEAT> uint64_t riscv_hart_mu_p<BASE, FEAT>::enter_trap(uint64_t flags, uint64_t addr, uint64_t instr) {
|
||||||
// flags are ACTIVE[31:31], CAUSE[30:16], TRAPID[15:0]
|
// flags are ACTIVE[31:31], CAUSE[30:16], TRAPID[15:0]
|
||||||
// calculate and write mcause val
|
// calculate and write mcause val
|
||||||
if(flags==std::numeric_limits<uint64_t>::max()) flags=this->reg.trap_state;
|
if(flags == std::numeric_limits<uint64_t>::max())
|
||||||
|
flags = this->reg.trap_state;
|
||||||
auto trap_id = bit_sub<0, 16>(flags);
|
auto trap_id = bit_sub<0, 16>(flags);
|
||||||
auto cause = bit_sub<16, 15>(flags);
|
auto cause = bit_sub<16, 15>(flags);
|
||||||
if (trap_id == 0 && cause == 11) cause = 0x8 + this->reg.PRIV; // adjust environment call cause
|
if(trap_id == 0 && cause == 11)
|
||||||
|
cause = 0x8 + this->reg.PRIV; // adjust environment call cause
|
||||||
// calculate effective privilege level
|
// calculate effective privilege level
|
||||||
unsigned new_priv = PRIV_M;
|
unsigned new_priv = PRIV_M;
|
||||||
if(trap_id == 0) { // exception
|
if(trap_id == 0) { // exception
|
||||||
@@ -1510,10 +1532,10 @@ template <typename BASE, features_e FEAT> uint64_t riscv_hart_mu_p<BASE, FEAT>::
|
|||||||
sprintf(buffer.data(), "0x%016lx", addr);
|
sprintf(buffer.data(), "0x%016lx", addr);
|
||||||
#endif
|
#endif
|
||||||
if((flags & 0xffffffff) != 0xffffffff)
|
if((flags & 0xffffffff) != 0xffffffff)
|
||||||
CLOG(INFO, disass) << (trap_id ? "Interrupt" : "Trap") << " with cause '"
|
CLOG(INFO, disass) << (trap_id ? "Interrupt" : "Trap") << " with cause '" << (trap_id ? irq_str[cause] : trap_str[cause]) << "' ("
|
||||||
<< (trap_id ? irq_str[cause] : trap_str[cause]) << "' (" << cause << ")"
|
<< cause << ")"
|
||||||
<< " at address " << buffer.data() << " occurred, changing privilege level from "
|
<< " at address " << buffer.data() << " occurred, changing privilege level from " << lvl[this->reg.PRIV]
|
||||||
<< lvl[this->reg.PRIV] << " to " << lvl[new_priv];
|
<< " to " << lvl[new_priv];
|
||||||
// reset trap state
|
// reset trap state
|
||||||
this->reg.PRIV = new_priv;
|
this->reg.PRIV = new_priv;
|
||||||
this->reg.trap_state = 0;
|
this->reg.trap_state = 0;
|
||||||
@@ -1546,8 +1568,7 @@ template <typename BASE, features_e FEAT> uint64_t riscv_hart_mu_p<BASE, FEAT>::
|
|||||||
}
|
}
|
||||||
// sets the pc to the value stored in the x epc register.
|
// sets the pc to the value stored in the x epc register.
|
||||||
this->reg.NEXT_PC = csr[uepc | inst_priv << 8];
|
this->reg.NEXT_PC = csr[uepc | inst_priv << 8];
|
||||||
CLOG(INFO, disass) << "Executing xRET , changing privilege level from " << lvl[cur_priv] << " to "
|
CLOG(INFO, disass) << "Executing xRET , changing privilege level from " << lvl[cur_priv] << " to " << lvl[this->reg.PRIV];
|
||||||
<< lvl[this->reg.PRIV];
|
|
||||||
check_interrupt();
|
check_interrupt();
|
||||||
}
|
}
|
||||||
return this->reg.NEXT_PC;
|
return this->reg.NEXT_PC;
|
||||||
|
|||||||
@@ -30,7 +30,8 @@
|
|||||||
*
|
*
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
#include "tgc_c.h"
|
// clang-format off
|
||||||
|
#include "tgc5c.h"
|
||||||
#include "util/ities.h"
|
#include "util/ities.h"
|
||||||
#include <util/logging.h>
|
#include <util/logging.h>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
@@ -39,18 +40,18 @@
|
|||||||
|
|
||||||
using namespace iss::arch;
|
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::tgc5c>::reg_names;
|
||||||
constexpr std::array<const char*, 36> iss::arch::traits<iss::arch::tgc_c>::reg_aliases;
|
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::tgc_c>::reg_bit_widths;
|
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::tgc_c>::reg_byte_offsets;
|
constexpr std::array<const uint32_t, 43> iss::arch::traits<iss::arch::tgc5c>::reg_byte_offsets;
|
||||||
|
|
||||||
tgc_c::tgc_c() = default;
|
tgc5c::tgc5c() = default;
|
||||||
|
|
||||||
tgc_c::~tgc_c() = default;
|
tgc5c::~tgc5c() = default;
|
||||||
|
|
||||||
void tgc_c::reset(uint64_t address) {
|
void tgc5c::reset(uint64_t address) {
|
||||||
auto base_ptr = reinterpret_cast<traits<tgc_c>::reg_t*>(get_regs_base_ptr());
|
auto base_ptr = reinterpret_cast<traits<tgc5c>::reg_t*>(get_regs_base_ptr());
|
||||||
for(size_t i=0; i<traits<tgc_c>::NUM_REGS; ++i)
|
for(size_t i=0; i<traits<tgc5c>::NUM_REGS; ++i)
|
||||||
*(base_ptr+i)=0;
|
*(base_ptr+i)=0;
|
||||||
reg.PC=address;
|
reg.PC=address;
|
||||||
reg.NEXT_PC=reg.PC;
|
reg.NEXT_PC=reg.PC;
|
||||||
@@ -59,11 +60,11 @@ void tgc_c::reset(uint64_t address) {
|
|||||||
reg.icount=0;
|
reg.icount=0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t *tgc_c::get_regs_base_ptr() {
|
uint8_t *tgc5c::get_regs_base_ptr() {
|
||||||
return reinterpret_cast<uint8_t*>(®);
|
return reinterpret_cast<uint8_t*>(®);
|
||||||
}
|
}
|
||||||
|
|
||||||
tgc_c::phys_addr_t tgc_c::virt2phys(const iss::addr_t &pc) {
|
tgc5c::phys_addr_t tgc5c::virt2phys(const iss::addr_t &addr) {
|
||||||
return phys_addr_t(pc); // change logical address to physical address
|
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_
|
#ifndef _TGC5C_H_
|
||||||
#define _TGC_C_H_
|
#define _TGC5C_H_
|
||||||
|
// clang-format off
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <iss/arch/traits.h>
|
#include <iss/arch/traits.h>
|
||||||
#include <iss/arch_if.h>
|
#include <iss/arch_if.h>
|
||||||
@@ -41,19 +41,19 @@
|
|||||||
namespace iss {
|
namespace iss {
|
||||||
namespace arch {
|
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{
|
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{
|
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=1073746180, MARCHID_VAL=2147483651, XLEN=32, INSTR_ALIGNMENT=2, RFS=32, fence=0, fencei=1, fencevmal=2, fencevmau=3, CSR_SIZE=4096, MUL_LEN=64};
|
enum constants {MISA_VAL=1073746180ULL, MARCHID_VAL=2147483651ULL, 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;
|
constexpr static unsigned FP_REGS_SIZE = 0;
|
||||||
|
|
||||||
@@ -141,49 +141,49 @@ template <> struct traits<tgc_c> {
|
|||||||
DIVU = 54,
|
DIVU = 54,
|
||||||
REM = 55,
|
REM = 55,
|
||||||
REMU = 56,
|
REMU = 56,
|
||||||
CADDI4SPN = 57,
|
C__ADDI4SPN = 57,
|
||||||
CLW = 58,
|
C__LW = 58,
|
||||||
CSW = 59,
|
C__SW = 59,
|
||||||
CADDI = 60,
|
C__ADDI = 60,
|
||||||
CNOP = 61,
|
C__NOP = 61,
|
||||||
CJAL = 62,
|
C__JAL = 62,
|
||||||
CLI = 63,
|
C__LI = 63,
|
||||||
CLUI = 64,
|
C__LUI = 64,
|
||||||
CADDI16SP = 65,
|
C__ADDI16SP = 65,
|
||||||
__reserved_clui = 66,
|
__reserved_clui = 66,
|
||||||
CSRLI = 67,
|
C__SRLI = 67,
|
||||||
CSRAI = 68,
|
C__SRAI = 68,
|
||||||
CANDI = 69,
|
C__ANDI = 69,
|
||||||
CSUB = 70,
|
C__SUB = 70,
|
||||||
CXOR = 71,
|
C__XOR = 71,
|
||||||
COR = 72,
|
C__OR = 72,
|
||||||
CAND = 73,
|
C__AND = 73,
|
||||||
CJ = 74,
|
C__J = 74,
|
||||||
CBEQZ = 75,
|
C__BEQZ = 75,
|
||||||
CBNEZ = 76,
|
C__BNEZ = 76,
|
||||||
CSLLI = 77,
|
C__SLLI = 77,
|
||||||
CLWSP = 78,
|
C__LWSP = 78,
|
||||||
CMV = 79,
|
C__MV = 79,
|
||||||
CJR = 80,
|
C__JR = 80,
|
||||||
__reserved_cmv = 81,
|
__reserved_cmv = 81,
|
||||||
CADD = 82,
|
C__ADD = 82,
|
||||||
CJALR = 83,
|
C__JALR = 83,
|
||||||
CEBREAK = 84,
|
C__EBREAK = 84,
|
||||||
CSWSP = 85,
|
C__SWSP = 85,
|
||||||
DII = 86,
|
DII = 86,
|
||||||
MAX_OPCODE
|
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 virt_addr_t = typename traits<tgc5c>::virt_addr_t;
|
||||||
using phys_addr_t = typename traits<tgc_c>::phys_addr_t;
|
using phys_addr_t = typename traits<tgc5c>::phys_addr_t;
|
||||||
using reg_t = typename traits<tgc_c>::reg_t;
|
using reg_t = typename traits<tgc5c>::reg_t;
|
||||||
using addr_t = typename traits<tgc_c>::addr_t;
|
using addr_t = typename traits<tgc5c>::addr_t;
|
||||||
|
|
||||||
tgc_c();
|
tgc5c();
|
||||||
~tgc_c();
|
~tgc5c();
|
||||||
|
|
||||||
void reset(uint64_t address=0) override;
|
void reset(uint64_t address=0) override;
|
||||||
|
|
||||||
@@ -195,14 +195,6 @@ struct tgc_c: public arch_if {
|
|||||||
|
|
||||||
inline uint64_t stop_code() { 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<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 phys_addr_t virt2phys(const iss::addr_t& addr);
|
||||||
|
|
||||||
virtual iss::sync_type needed_sync() const { return iss::NO_SYNC; }
|
virtual iss::sync_type needed_sync() const { return iss::NO_SYNC; }
|
||||||
@@ -211,7 +203,7 @@ struct tgc_c: public arch_if {
|
|||||||
|
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
#pragma pack(push, 1)
|
||||||
struct TGC_C_regs {
|
struct TGC5C_regs {
|
||||||
uint32_t X0 = 0;
|
uint32_t X0 = 0;
|
||||||
uint32_t X1 = 0;
|
uint32_t X1 = 0;
|
||||||
uint32_t X2 = 0;
|
uint32_t X2 = 0;
|
||||||
@@ -267,4 +259,5 @@ struct tgc_c: public arch_if {
|
|||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* _TGC_C_H_ */
|
#endif /* _TGC5C_H_ */
|
||||||
|
// clang-format on
|
||||||
@@ -1,175 +0,0 @@
|
|||||||
#include "tgc_c.h"
|
|
||||||
#include <vector>
|
|
||||||
#include <array>
|
|
||||||
#include <cstdlib>
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
namespace iss {
|
|
||||||
namespace arch {
|
|
||||||
namespace {
|
|
||||||
// according to
|
|
||||||
// https://stackoverflow.com/questions/8871204/count-number-of-1s-in-binary-representation
|
|
||||||
#ifdef __GCC__
|
|
||||||
constexpr size_t bit_count(uint32_t u) { return __builtin_popcount(u); }
|
|
||||||
#elif __cplusplus < 201402L
|
|
||||||
constexpr size_t uCount(uint32_t u) { return u - ((u >> 1) & 033333333333) - ((u >> 2) & 011111111111); }
|
|
||||||
constexpr size_t bit_count(uint32_t u) { return ((uCount(u) + (uCount(u) >> 3)) & 030707070707) % 63; }
|
|
||||||
#else
|
|
||||||
constexpr size_t bit_count(uint32_t u) {
|
|
||||||
size_t uCount = u - ((u >> 1) & 033333333333) - ((u >> 2) & 011111111111);
|
|
||||||
return ((uCount + (uCount >> 3)) & 030707070707) % 63;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
using opcode_e = traits<tgc_c>::opcode_e;
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* start opcode definitions
|
|
||||||
****************************************************************************/
|
|
||||||
struct instruction_desriptor {
|
|
||||||
size_t length;
|
|
||||||
uint32_t value;
|
|
||||||
uint32_t mask;
|
|
||||||
opcode_e op;
|
|
||||||
};
|
|
||||||
|
|
||||||
const std::array<instruction_desriptor, 90> instr_descr = {{
|
|
||||||
/* entries are: size, valid value, valid mask, function ptr */
|
|
||||||
{32, 0b00000000000000000000000000110111, 0b00000000000000000000000001111111, opcode_e::LUI},
|
|
||||||
{32, 0b00000000000000000000000000010111, 0b00000000000000000000000001111111, opcode_e::AUIPC},
|
|
||||||
{32, 0b00000000000000000000000001101111, 0b00000000000000000000000001111111, opcode_e::JAL},
|
|
||||||
{32, 0b00000000000000000000000001100111, 0b00000000000000000111000001111111, opcode_e::JALR},
|
|
||||||
{32, 0b00000000000000000000000001100011, 0b00000000000000000111000001111111, opcode_e::BEQ},
|
|
||||||
{32, 0b00000000000000000001000001100011, 0b00000000000000000111000001111111, opcode_e::BNE},
|
|
||||||
{32, 0b00000000000000000100000001100011, 0b00000000000000000111000001111111, opcode_e::BLT},
|
|
||||||
{32, 0b00000000000000000101000001100011, 0b00000000000000000111000001111111, opcode_e::BGE},
|
|
||||||
{32, 0b00000000000000000110000001100011, 0b00000000000000000111000001111111, opcode_e::BLTU},
|
|
||||||
{32, 0b00000000000000000111000001100011, 0b00000000000000000111000001111111, opcode_e::BGEU},
|
|
||||||
{32, 0b00000000000000000000000000000011, 0b00000000000000000111000001111111, opcode_e::LB},
|
|
||||||
{32, 0b00000000000000000001000000000011, 0b00000000000000000111000001111111, opcode_e::LH},
|
|
||||||
{32, 0b00000000000000000010000000000011, 0b00000000000000000111000001111111, opcode_e::LW},
|
|
||||||
{32, 0b00000000000000000100000000000011, 0b00000000000000000111000001111111, opcode_e::LBU},
|
|
||||||
{32, 0b00000000000000000101000000000011, 0b00000000000000000111000001111111, opcode_e::LHU},
|
|
||||||
{32, 0b00000000000000000000000000100011, 0b00000000000000000111000001111111, opcode_e::SB},
|
|
||||||
{32, 0b00000000000000000001000000100011, 0b00000000000000000111000001111111, opcode_e::SH},
|
|
||||||
{32, 0b00000000000000000010000000100011, 0b00000000000000000111000001111111, opcode_e::SW},
|
|
||||||
{32, 0b00000000000000000000000000010011, 0b00000000000000000111000001111111, opcode_e::ADDI},
|
|
||||||
{32, 0b00000000000000000010000000010011, 0b00000000000000000111000001111111, opcode_e::SLTI},
|
|
||||||
{32, 0b00000000000000000011000000010011, 0b00000000000000000111000001111111, opcode_e::SLTIU},
|
|
||||||
{32, 0b00000000000000000100000000010011, 0b00000000000000000111000001111111, opcode_e::XORI},
|
|
||||||
{32, 0b00000000000000000110000000010011, 0b00000000000000000111000001111111, opcode_e::ORI},
|
|
||||||
{32, 0b00000000000000000111000000010011, 0b00000000000000000111000001111111, opcode_e::ANDI},
|
|
||||||
{32, 0b00000000000000000001000000010011, 0b11111110000000000111000001111111, opcode_e::SLLI},
|
|
||||||
{32, 0b00000000000000000101000000010011, 0b11111110000000000111000001111111, opcode_e::SRLI},
|
|
||||||
{32, 0b01000000000000000101000000010011, 0b11111110000000000111000001111111, opcode_e::SRAI},
|
|
||||||
{32, 0b00000000000000000000000000110011, 0b11111110000000000111000001111111, opcode_e::ADD},
|
|
||||||
{32, 0b01000000000000000000000000110011, 0b11111110000000000111000001111111, opcode_e::SUB},
|
|
||||||
{32, 0b00000000000000000001000000110011, 0b11111110000000000111000001111111, opcode_e::SLL},
|
|
||||||
{32, 0b00000000000000000010000000110011, 0b11111110000000000111000001111111, opcode_e::SLT},
|
|
||||||
{32, 0b00000000000000000011000000110011, 0b11111110000000000111000001111111, opcode_e::SLTU},
|
|
||||||
{32, 0b00000000000000000100000000110011, 0b11111110000000000111000001111111, opcode_e::XOR},
|
|
||||||
{32, 0b00000000000000000101000000110011, 0b11111110000000000111000001111111, opcode_e::SRL},
|
|
||||||
{32, 0b01000000000000000101000000110011, 0b11111110000000000111000001111111, opcode_e::SRA},
|
|
||||||
{32, 0b00000000000000000110000000110011, 0b11111110000000000111000001111111, opcode_e::OR},
|
|
||||||
{32, 0b00000000000000000111000000110011, 0b11111110000000000111000001111111, opcode_e::AND},
|
|
||||||
{32, 0b00000000000000000000000000001111, 0b00000000000000000111000001111111, opcode_e::FENCE},
|
|
||||||
{32, 0b00000000000000000000000001110011, 0b11111111111111111111111111111111, opcode_e::ECALL},
|
|
||||||
{32, 0b00000000000100000000000001110011, 0b11111111111111111111111111111111, opcode_e::EBREAK},
|
|
||||||
{32, 0b00000000001000000000000001110011, 0b11111111111111111111111111111111, opcode_e::URET},
|
|
||||||
{32, 0b00010000001000000000000001110011, 0b11111111111111111111111111111111, opcode_e::SRET},
|
|
||||||
{32, 0b00110000001000000000000001110011, 0b11111111111111111111111111111111, opcode_e::MRET},
|
|
||||||
{32, 0b00010000010100000000000001110011, 0b11111111111111111111111111111111, opcode_e::WFI},
|
|
||||||
{32, 0b01111011001000000000000001110011, 0b11111111111111111111111111111111, opcode_e::DRET},
|
|
||||||
{32, 0b00000000000000000001000001110011, 0b00000000000000000111000001111111, opcode_e::CSRRW},
|
|
||||||
{32, 0b00000000000000000010000001110011, 0b00000000000000000111000001111111, opcode_e::CSRRS},
|
|
||||||
{32, 0b00000000000000000011000001110011, 0b00000000000000000111000001111111, opcode_e::CSRRC},
|
|
||||||
{32, 0b00000000000000000101000001110011, 0b00000000000000000111000001111111, opcode_e::CSRRWI},
|
|
||||||
{32, 0b00000000000000000110000001110011, 0b00000000000000000111000001111111, opcode_e::CSRRSI},
|
|
||||||
{32, 0b00000000000000000111000001110011, 0b00000000000000000111000001111111, opcode_e::CSRRCI},
|
|
||||||
{32, 0b00000000000000000001000000001111, 0b00000000000000000111000001111111, opcode_e::FENCE_I},
|
|
||||||
{32, 0b00000010000000000000000000110011, 0b11111110000000000111000001111111, opcode_e::MUL},
|
|
||||||
{32, 0b00000010000000000001000000110011, 0b11111110000000000111000001111111, opcode_e::MULH},
|
|
||||||
{32, 0b00000010000000000010000000110011, 0b11111110000000000111000001111111, opcode_e::MULHSU},
|
|
||||||
{32, 0b00000010000000000011000000110011, 0b11111110000000000111000001111111, opcode_e::MULHU},
|
|
||||||
{32, 0b00000010000000000100000000110011, 0b11111110000000000111000001111111, opcode_e::DIV},
|
|
||||||
{32, 0b00000010000000000101000000110011, 0b11111110000000000111000001111111, opcode_e::DIVU},
|
|
||||||
{32, 0b00000010000000000110000000110011, 0b11111110000000000111000001111111, opcode_e::REM},
|
|
||||||
{32, 0b00000010000000000111000000110011, 0b11111110000000000111000001111111, opcode_e::REMU},
|
|
||||||
{16, 0b0000000000000000, 0b1110000000000011, opcode_e::CADDI4SPN},
|
|
||||||
{16, 0b0100000000000000, 0b1110000000000011, opcode_e::CLW},
|
|
||||||
{16, 0b1100000000000000, 0b1110000000000011, opcode_e::CSW},
|
|
||||||
{16, 0b0000000000000001, 0b1110000000000011, opcode_e::CADDI},
|
|
||||||
{16, 0b0000000000000001, 0b1110111110000011, opcode_e::CNOP},
|
|
||||||
{16, 0b0010000000000001, 0b1110000000000011, opcode_e::CJAL},
|
|
||||||
{16, 0b0100000000000001, 0b1110000000000011, opcode_e::CLI},
|
|
||||||
{16, 0b0110000000000001, 0b1110000000000011, opcode_e::CLUI},
|
|
||||||
{16, 0b0110000100000001, 0b1110111110000011, opcode_e::CADDI16SP},
|
|
||||||
{16, 0b0110000000000001, 0b1111000001111111, opcode_e::__reserved_clui},
|
|
||||||
{16, 0b1000000000000001, 0b1111110000000011, opcode_e::CSRLI},
|
|
||||||
{16, 0b1000010000000001, 0b1111110000000011, opcode_e::CSRAI},
|
|
||||||
{16, 0b1000100000000001, 0b1110110000000011, opcode_e::CANDI},
|
|
||||||
{16, 0b1000110000000001, 0b1111110001100011, opcode_e::CSUB},
|
|
||||||
{16, 0b1000110000100001, 0b1111110001100011, opcode_e::CXOR},
|
|
||||||
{16, 0b1000110001000001, 0b1111110001100011, opcode_e::COR},
|
|
||||||
{16, 0b1000110001100001, 0b1111110001100011, opcode_e::CAND},
|
|
||||||
{16, 0b1010000000000001, 0b1110000000000011, opcode_e::CJ},
|
|
||||||
{16, 0b1100000000000001, 0b1110000000000011, opcode_e::CBEQZ},
|
|
||||||
{16, 0b1110000000000001, 0b1110000000000011, opcode_e::CBNEZ},
|
|
||||||
{16, 0b0000000000000010, 0b1111000000000011, opcode_e::CSLLI},
|
|
||||||
{16, 0b0100000000000010, 0b1110000000000011, opcode_e::CLWSP},
|
|
||||||
{16, 0b1000000000000010, 0b1111000000000011, opcode_e::CMV},
|
|
||||||
{16, 0b1000000000000010, 0b1111000001111111, opcode_e::CJR},
|
|
||||||
{16, 0b1000000000000010, 0b1111111111111111, opcode_e::__reserved_cmv},
|
|
||||||
{16, 0b1001000000000010, 0b1111000000000011, opcode_e::CADD},
|
|
||||||
{16, 0b1001000000000010, 0b1111000001111111, opcode_e::CJALR},
|
|
||||||
{16, 0b1001000000000010, 0b1111111111111111, opcode_e::CEBREAK},
|
|
||||||
{16, 0b1100000000000010, 0b1110000000000011, opcode_e::CSWSP},
|
|
||||||
{16, 0b0000000000000000, 0b1111111111111111, opcode_e::DII},
|
|
||||||
}};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
struct instruction_decoder<tgc_c> {
|
|
||||||
using opcode_e = traits<tgc_c>::opcode_e;
|
|
||||||
using code_word_t=traits<tgc_c>::code_word_t;
|
|
||||||
|
|
||||||
struct instruction_pattern {
|
|
||||||
uint32_t value;
|
|
||||||
uint32_t mask;
|
|
||||||
opcode_e id;
|
|
||||||
};
|
|
||||||
|
|
||||||
std::array<std::vector<instruction_pattern>, 4> qlut;
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
unsigned decode_instruction(T);
|
|
||||||
|
|
||||||
instruction_decoder() {
|
|
||||||
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);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<>
|
|
||||||
unsigned instruction_decoder<tgc_c>::decode_instruction<traits<tgc_c>::code_word_t>(traits<tgc_c>::code_word_t instr){
|
|
||||||
auto res = std::find_if(std::begin(qlut[instr&0x3]), std::end(qlut[instr&0x3]), [instr](instruction_pattern const& e){
|
|
||||||
return !((instr&e.mask) ^ e.value );
|
|
||||||
});
|
|
||||||
return static_cast<unsigned>(res!=std::end(qlut[instr&0x3])? res->id : opcode_e::MAX_OPCODE);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
std::unique_ptr<instruction_decoder<tgc_c>> traits<tgc_c>::get_decoder(){
|
|
||||||
return std::make_unique<instruction_decoder<tgc_c>>();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -2,49 +2,56 @@
|
|||||||
#define _ISS_ARCH_TGC_MAPPER_H
|
#define _ISS_ARCH_TGC_MAPPER_H
|
||||||
|
|
||||||
#include "riscv_hart_m_p.h"
|
#include "riscv_hart_m_p.h"
|
||||||
#include "tgc_c.h"
|
#include "tgc5c.h"
|
||||||
using tgc_c_plat_type = iss::arch::riscv_hart_m_p<iss::arch::tgc_c>;
|
using tgc5c_plat_type = iss::arch::riscv_hart_m_p<iss::arch::tgc5c>;
|
||||||
#ifdef CORE_TGC_A
|
#ifdef CORE_TGC5A
|
||||||
#include "riscv_hart_m_p.h"
|
#include "riscv_hart_m_p.h"
|
||||||
#include <iss/arch/tgc_a.h>
|
#include <iss/arch/tgc5a.h>
|
||||||
using tgc_a_plat_type = iss::arch::riscv_hart_m_p<iss::arch::tgc_a>;
|
using tgc5a_plat_type = iss::arch::riscv_hart_m_p<iss::arch::tgc5a>;
|
||||||
#endif
|
#endif
|
||||||
#ifdef CORE_TGC_B
|
#ifdef CORE_TGC5B
|
||||||
#include "riscv_hart_m_p.h"
|
#include "riscv_hart_m_p.h"
|
||||||
#include <iss/arch/tgc_b.h>
|
#include <iss/arch/tgc5b.h>
|
||||||
using tgc_b_plat_type = iss::arch::riscv_hart_m_p<iss::arch::tgc_b>;
|
using tgc5b_plat_type = iss::arch::riscv_hart_m_p<iss::arch::tgc5b>;
|
||||||
#endif
|
#endif
|
||||||
#ifdef CORE_TGC_C_XRB_NN
|
#ifdef CORE_TGC5C_XRB_NN
|
||||||
#include "riscv_hart_m_p.h"
|
|
||||||
#include "hwl.h"
|
#include "hwl.h"
|
||||||
#include <iss/arch/tgc_c_xrb_nn.h>
|
#include "riscv_hart_m_p.h"
|
||||||
using tgc_c_xrb_nn_plat_type = iss::arch::hwl<iss::arch::riscv_hart_m_p<iss::arch::tgc_c_xrb_nn>>;
|
#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
|
#endif
|
||||||
#ifdef CORE_TGC_D
|
#ifdef CORE_TGC5D
|
||||||
#include "riscv_hart_mu_p.h"
|
#include "riscv_hart_mu_p.h"
|
||||||
#include <iss/arch/tgc_d.h>
|
#include <iss/arch/tgc5d.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)>;
|
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
|
#endif
|
||||||
#ifdef CORE_TGC_D_XRB_MAC
|
#ifdef CORE_TGC5D_XRB_MAC
|
||||||
#include "riscv_hart_mu_p.h"
|
#include "riscv_hart_mu_p.h"
|
||||||
#include <iss/arch/tgc_d_xrb_mac.h>
|
#include <iss/arch/tgc5d_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)>;
|
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
|
#endif
|
||||||
#ifdef CORE_TGC_D_XRB_NN
|
#ifdef CORE_TGC5D_XRB_NN
|
||||||
#include "riscv_hart_mu_p.h"
|
|
||||||
#include "hwl.h"
|
#include "hwl.h"
|
||||||
#include <iss/arch/tgc_d_xrb_nn.h>
|
|
||||||
using tgc_d_xrb_nn_plat_type = iss::arch::hwl<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 "riscv_hart_mu_p.h"
|
||||||
#include <iss/arch/tgc_e.h>
|
#include <iss/arch/tgc5d_xrb_nn.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)>;
|
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
|
#endif
|
||||||
#ifdef CORE_TGC_X
|
#ifdef CORE_TGC5E
|
||||||
#include "riscv_hart_mu_p.h"
|
#include "riscv_hart_mu_p.h"
|
||||||
#include <iss/arch/tgc_x.h>
|
#include <iss/arch/tgc5e.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)>;
|
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
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -36,10 +36,10 @@
|
|||||||
#define _RISCV_HART_M_P_WT_CACHE_H
|
#define _RISCV_HART_M_P_WT_CACHE_H
|
||||||
|
|
||||||
#include <iss/vm_types.h>
|
#include <iss/vm_types.h>
|
||||||
#include <util/ities.h>
|
|
||||||
#include <vector>
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <util/ities.h>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace iss {
|
namespace iss {
|
||||||
namespace arch {
|
namespace arch {
|
||||||
@@ -50,11 +50,13 @@ struct line {
|
|||||||
uint64_t tag_addr{0};
|
uint64_t tag_addr{0};
|
||||||
state st{state::INVALID};
|
state st{state::INVALID};
|
||||||
std::vector<uint8_t> data;
|
std::vector<uint8_t> data;
|
||||||
line(unsigned line_sz): data(line_sz) {}
|
line(unsigned line_sz)
|
||||||
|
: data(line_sz) {}
|
||||||
};
|
};
|
||||||
struct set {
|
struct set {
|
||||||
std::vector<line> ways;
|
std::vector<line> ways;
|
||||||
set(unsigned ways_count, line const& l): ways(ways_count, l) {}
|
set(unsigned ways_count, line const& l)
|
||||||
|
: ways(ways_count, l) {}
|
||||||
};
|
};
|
||||||
struct cache {
|
struct cache {
|
||||||
std::vector<set> sets;
|
std::vector<set> sets;
|
||||||
@@ -69,7 +71,7 @@ struct cache {
|
|||||||
struct wt_policy {
|
struct wt_policy {
|
||||||
bool is_cacheline_hit(cache& c);
|
bool is_cacheline_hit(cache& c);
|
||||||
};
|
};
|
||||||
}
|
} // namespace cache
|
||||||
|
|
||||||
// write thru, allocate on read, direct mapped or set-associative with round-robin replacement policy
|
// write thru, allocate on read, direct mapped or set-associative with round-robin replacement policy
|
||||||
template <typename BASE> class wt_cache : public BASE {
|
template <typename BASE> class wt_cache : public BASE {
|
||||||
@@ -81,7 +83,7 @@ public:
|
|||||||
using mem_write_f = typename BASE::mem_write_f;
|
using mem_write_f = typename BASE::mem_write_f;
|
||||||
using phys_addr_t = typename BASE::phys_addr_t;
|
using phys_addr_t = typename BASE::phys_addr_t;
|
||||||
|
|
||||||
wt_cache();
|
wt_cache(feature_config cfg = feature_config{});
|
||||||
virtual ~wt_cache() = default;
|
virtual ~wt_cache() = default;
|
||||||
|
|
||||||
unsigned size{4096};
|
unsigned size{4096};
|
||||||
@@ -89,6 +91,7 @@ public:
|
|||||||
unsigned ways{1};
|
unsigned ways{1};
|
||||||
uint64_t io_address{0xf0000000};
|
uint64_t io_address{0xf0000000};
|
||||||
uint64_t io_addr_mask{0xf0000000};
|
uint64_t io_addr_mask{0xf0000000};
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
iss::status read_cache(phys_addr_t addr, unsigned, uint8_t* const);
|
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);
|
iss::status write_cache(phys_addr_t addr, unsigned, uint8_t const* const);
|
||||||
@@ -96,14 +99,14 @@ protected:
|
|||||||
std::function<mem_write_f> cache_mem_wr_delegate;
|
std::function<mem_write_f> cache_mem_wr_delegate;
|
||||||
std::unique_ptr<cache::cache> dcache_ptr;
|
std::unique_ptr<cache::cache> dcache_ptr;
|
||||||
std::unique_ptr<cache::cache> icache_ptr;
|
std::unique_ptr<cache::cache> icache_ptr;
|
||||||
size_t get_way_select() {
|
size_t get_way_select() { return 0; }
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
template <typename BASE>
|
template <typename BASE>
|
||||||
inline wt_cache<BASE>::wt_cache() {
|
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(
|
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 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); });
|
[this](phys_addr_t a, unsigned l, uint8_t const* const d) -> iss::status { return write_cache(a, l, d); });
|
||||||
@@ -111,8 +114,7 @@ inline wt_cache<BASE>::wt_cache() {
|
|||||||
cache_mem_wr_delegate = cb.second;
|
cache_mem_wr_delegate = cb.second;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename BASE>
|
template <typename BASE> iss::status iss::arch::wt_cache<BASE>::read_cache(phys_addr_t a, unsigned l, uint8_t* const d) {
|
||||||
iss::status iss::arch::wt_cache<BASE>::read_cache(phys_addr_t a, unsigned l, uint8_t* const d) {
|
|
||||||
if(!icache_ptr) {
|
if(!icache_ptr) {
|
||||||
icache_ptr.reset(new cache::cache(size, line_sz, ways));
|
icache_ptr.reset(new cache::cache(size, line_sz, ways));
|
||||||
dcache_ptr.reset(new cache::cache(size, line_sz, ways));
|
dcache_ptr.reset(new cache::cache(size, line_sz, ways));
|
||||||
@@ -143,8 +145,7 @@ iss::status iss::arch::wt_cache<BASE>::read_cache(phys_addr_t a, unsigned l, uin
|
|||||||
return cache_mem_rd_delegate(a, l, d);
|
return cache_mem_rd_delegate(a, l, d);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename BASE>
|
template <typename BASE> iss::status iss::arch::wt_cache<BASE>::write_cache(phys_addr_t a, unsigned l, const uint8_t* const d) {
|
||||||
iss::status iss::arch::wt_cache<BASE>::write_cache(phys_addr_t a, unsigned l, const uint8_t* const d) {
|
|
||||||
if(!dcache_ptr)
|
if(!dcache_ptr)
|
||||||
dcache_ptr.reset(new cache::cache(size, line_sz, ways));
|
dcache_ptr.reset(new cache::cache(size, line_sz, ways));
|
||||||
auto res = cache_mem_wr_delegate(a, l, d);
|
auto res = cache_mem_wr_delegate(a, l, d);
|
||||||
@@ -164,8 +165,6 @@ iss::status iss::arch::wt_cache<BASE>::write_cache(phys_addr_t a, unsigned l, co
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace arch
|
} // namespace arch
|
||||||
} // namespace iss
|
} // namespace iss
|
||||||
|
|
||||||
|
|||||||
@@ -84,8 +84,7 @@ public:
|
|||||||
target byte order. If register is not available
|
target byte order. If register is not available
|
||||||
corresponding bytes in avail_buf are 0, otherwise
|
corresponding bytes in avail_buf are 0, otherwise
|
||||||
avail buf is 1 */
|
avail buf is 1 */
|
||||||
status read_single_register(unsigned int reg_no, std::vector<uint8_t> &buf,
|
status read_single_register(unsigned int reg_no, std::vector<uint8_t>& buf, std::vector<uint8_t>& avail_buf) override;
|
||||||
std::vector<uint8_t> &avail_buf) override;
|
|
||||||
|
|
||||||
/* Write one register. buf is 4-byte aligned and it is in target byte
|
/* Write one register. buf is 4-byte aligned and it is in target byte
|
||||||
order */
|
order */
|
||||||
@@ -103,8 +102,8 @@ public:
|
|||||||
|
|
||||||
status process_query(unsigned int& mask, const rp_thread_ref& arg, rp_thread_info& info) override;
|
status process_query(unsigned int& mask, const rp_thread_ref& arg, rp_thread_info& info) override;
|
||||||
|
|
||||||
status thread_list_query(int first, const rp_thread_ref &arg, std::vector<rp_thread_ref> &result, size_t max_num,
|
status thread_list_query(int first, const rp_thread_ref& arg, std::vector<rp_thread_ref>& result, size_t max_num, size_t& num,
|
||||||
size_t &num, bool &done) override;
|
bool& done) override;
|
||||||
|
|
||||||
status current_thread_query(rp_thread_ref& thread) override;
|
status current_thread_query(rp_thread_ref& thread) override;
|
||||||
|
|
||||||
@@ -124,8 +123,7 @@ public:
|
|||||||
|
|
||||||
status remove_break(break_type 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,
|
status resume_from_addr(bool step, int sig, uint64_t addr, rp_thread_ref thread, std::function<void(unsigned)> stop_callback) override;
|
||||||
std::function<void(unsigned)> stop_callback) override;
|
|
||||||
|
|
||||||
status target_xml_query(std::string& out_buf) 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.
|
* set if all threads are processed.
|
||||||
*/
|
*/
|
||||||
template <typename ARCH>
|
template <typename ARCH>
|
||||||
status riscv_target_adapter<ARCH>::thread_list_query(int first, const rp_thread_ref &arg,
|
status riscv_target_adapter<ARCH>::thread_list_query(int first, const rp_thread_ref& arg, std::vector<rp_thread_ref>& result,
|
||||||
std::vector<rp_thread_ref> &result, size_t max_num, size_t &num,
|
size_t max_num, size_t& num, bool& done) {
|
||||||
bool &done) {
|
|
||||||
if(first == 0) {
|
if(first == 0) {
|
||||||
result.clear();
|
result.clear();
|
||||||
result.push_back(thread_idx);
|
result.push_back(thread_idx);
|
||||||
@@ -176,8 +173,7 @@ template <typename ARCH> status riscv_target_adapter<ARCH>::current_thread_query
|
|||||||
return Ok;
|
return Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename ARCH>
|
template <typename ARCH> status riscv_target_adapter<ARCH>::read_registers(std::vector<uint8_t>& data, std::vector<uint8_t>& avail) {
|
||||||
status riscv_target_adapter<ARCH>::read_registers(std::vector<uint8_t> &data, std::vector<uint8_t> &avail) {
|
|
||||||
LOG(TRACE) << "reading target registers";
|
LOG(TRACE) << "reading target registers";
|
||||||
// return idx<0?:;
|
// return idx<0?:;
|
||||||
data.clear();
|
data.clear();
|
||||||
@@ -239,8 +235,7 @@ template <typename ARCH> status riscv_target_adapter<ARCH>::write_registers(cons
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename ARCH>
|
template <typename ARCH>
|
||||||
status riscv_target_adapter<ARCH>::read_single_register(unsigned int reg_no, std::vector<uint8_t> &data,
|
status riscv_target_adapter<ARCH>::read_single_register(unsigned int reg_no, std::vector<uint8_t>& data, std::vector<uint8_t>& avail) {
|
||||||
std::vector<uint8_t> &avail) {
|
|
||||||
if(reg_no < 65) {
|
if(reg_no < 65) {
|
||||||
// auto reg_size = arch::traits<ARCH>::reg_bit_width(static_cast<typename
|
// auto reg_size = arch::traits<ARCH>::reg_bit_width(static_cast<typename
|
||||||
// arch::traits<ARCH>::reg_e>(reg_no))/8;
|
// 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;
|
return data.size() > 0 ? Ok : Err;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename ARCH>
|
template <typename ARCH> status riscv_target_adapter<ARCH>::write_single_register(unsigned int reg_no, const std::vector<uint8_t>& data) {
|
||||||
status riscv_target_adapter<ARCH>::write_single_register(unsigned int reg_no, const std::vector<uint8_t> &data) {
|
|
||||||
if(reg_no < 65) {
|
if(reg_no < 65) {
|
||||||
auto* reg_base = core->get_regs_base_ptr();
|
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;
|
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;
|
return NotSupported;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename ARCH>
|
template <typename ARCH> status riscv_target_adapter<ARCH>::offsets_query(uint64_t& text, uint64_t& data, uint64_t& bss) {
|
||||||
status riscv_target_adapter<ARCH>::offsets_query(uint64_t &text, uint64_t &data, uint64_t &bss) {
|
|
||||||
text = 0;
|
text = 0;
|
||||||
data = 0;
|
data = 0;
|
||||||
bss = 0;
|
bss = 0;
|
||||||
return Ok;
|
return Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename ARCH> status riscv_target_adapter<ARCH>::crc_query(uint64_t addr, size_t len, uint32_t &val) {
|
template <typename ARCH> status riscv_target_adapter<ARCH>::crc_query(uint64_t addr, size_t len, uint32_t& val) { return NotSupported; }
|
||||||
return NotSupported;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename ARCH> status riscv_target_adapter<ARCH>::raw_query(std::string in_buf, std::string &out_buf) {
|
template <typename ARCH> status riscv_target_adapter<ARCH>::raw_query(std::string in_buf, std::string& out_buf) { return NotSupported; }
|
||||||
return NotSupported;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename ARCH> status riscv_target_adapter<ARCH>::threadinfo_query(int first, std::string& out_buf) {
|
template <typename ARCH> status riscv_target_adapter<ARCH>::threadinfo_query(int first, std::string& out_buf) {
|
||||||
if(first) {
|
if(first) {
|
||||||
@@ -317,8 +306,7 @@ template <typename ARCH> status riscv_target_adapter<ARCH>::threadinfo_query(int
|
|||||||
return Ok;
|
return Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename ARCH>
|
template <typename ARCH> status riscv_target_adapter<ARCH>::threadextrainfo_query(const rp_thread_ref& thread, std::string& out_buf) {
|
||||||
status riscv_target_adapter<ARCH>::threadextrainfo_query(const rp_thread_ref &thread, std::string &out_buf) {
|
|
||||||
std::array<char, 20> buf;
|
std::array<char, 20> buf;
|
||||||
memset(buf.data(), 0, 20);
|
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);
|
sprintf(buf.data(), "%02x%02x%02x%02x%02x%02x%02x%02x%02x", 'R', 'u', 'n', 'n', 'a', 'b', 'l', 'e', 0);
|
||||||
@@ -340,8 +328,8 @@ template <typename ARCH> status riscv_target_adapter<ARCH>::add_break(break_type
|
|||||||
auto saddr = map_addr({iss::access_type::FETCH, iss::address_type::PHYSICAL, 0, addr});
|
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});
|
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);
|
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
|
LOG(TRACE) << "Adding breakpoint with handle " << target_adapter_base::bp_count << " for addr 0x" << std::hex << saddr.val
|
||||||
<< saddr.val << std::dec;
|
<< std::dec;
|
||||||
LOG(TRACE) << "Now having " << target_adapter_base::bp_lut.size() << " breakpoints";
|
LOG(TRACE) << "Now having " << target_adapter_base::bp_lut.size() << " breakpoints";
|
||||||
return Ok;
|
return Ok;
|
||||||
}
|
}
|
||||||
@@ -357,8 +345,7 @@ template <typename ARCH> status riscv_target_adapter<ARCH>::remove_break(break_t
|
|||||||
auto saddr = map_addr({iss::access_type::FETCH, iss::address_type::PHYSICAL, 0, addr});
|
auto saddr = map_addr({iss::access_type::FETCH, iss::address_type::PHYSICAL, 0, addr});
|
||||||
unsigned handle = target_adapter_base::bp_lut.getEntry(saddr.val);
|
unsigned handle = target_adapter_base::bp_lut.getEntry(saddr.val);
|
||||||
if(handle) {
|
if(handle) {
|
||||||
LOG(TRACE) << "Removing breakpoint with handle " << handle << " for addr 0x" << std::hex << saddr.val
|
LOG(TRACE) << "Removing breakpoint with handle " << handle << " for addr 0x" << std::hex << saddr.val << std::dec;
|
||||||
<< std::dec;
|
|
||||||
// TODO: check length of addr range
|
// TODO: check length of addr range
|
||||||
target_adapter_base::bp_lut.removeEntry(handle);
|
target_adapter_base::bp_lut.removeEntry(handle);
|
||||||
LOG(TRACE) << "Now having " << target_adapter_base::bp_lut.size() << " breakpoints";
|
LOG(TRACE) << "Now having " << target_adapter_base::bp_lut.size() << " breakpoints";
|
||||||
@@ -468,7 +455,7 @@ template <typename ARCH> status riscv_target_adapter<ARCH>::target_xml_query(std
|
|||||||
</target>
|
</target>
|
||||||
|
|
||||||
*/
|
*/
|
||||||
}
|
} // namespace debugger
|
||||||
}
|
} // namespace iss
|
||||||
|
|
||||||
#endif /* _ISS_DEBUGGER_RISCV_TARGET_ADAPTER_H_ */
|
#endif /* _ISS_DEBUGGER_RISCV_TARGET_ADAPTER_H_ */
|
||||||
|
|||||||
@@ -33,12 +33,12 @@
|
|||||||
#ifndef _ISS_FACTORY_H_
|
#ifndef _ISS_FACTORY_H_
|
||||||
#define _ISS_FACTORY_H_
|
#define _ISS_FACTORY_H_
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <functional>
|
||||||
#include <iss/iss.h>
|
#include <iss/iss.h>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <unordered_map>
|
|
||||||
#include <functional>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <algorithm>
|
#include <unordered_map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace iss {
|
namespace iss {
|
||||||
@@ -46,8 +46,7 @@ namespace iss {
|
|||||||
using cpu_ptr = std::unique_ptr<iss::arch_if>;
|
using cpu_ptr = std::unique_ptr<iss::arch_if>;
|
||||||
using vm_ptr = std::unique_ptr<iss::vm_if>;
|
using vm_ptr = std::unique_ptr<iss::vm_if>;
|
||||||
|
|
||||||
template<typename PLAT>
|
template <typename PLAT> std::tuple<cpu_ptr, vm_ptr> create_cpu(std::string const& backend, unsigned gdb_port) {
|
||||||
std::tuple<cpu_ptr, vm_ptr> create_cpu(std::string const& backend, unsigned gdb_port){
|
|
||||||
using core_type = typename PLAT::core;
|
using core_type = typename PLAT::core;
|
||||||
core_type* lcpu = new PLAT();
|
core_type* lcpu = new PLAT();
|
||||||
if(backend == "interp")
|
if(backend == "interp")
|
||||||
@@ -63,7 +62,6 @@ std::tuple<cpu_ptr, vm_ptr> create_cpu(std::string const& backend, unsigned gdb_
|
|||||||
return {nullptr, nullptr};
|
return {nullptr, nullptr};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class core_factory {
|
class core_factory {
|
||||||
using cpu_ptr = std::unique_ptr<iss::arch_if>;
|
using cpu_ptr = std::unique_ptr<iss::arch_if>;
|
||||||
using vm_ptr = std::unique_ptr<iss::vm_if>;
|
using vm_ptr = std::unique_ptr<iss::vm_if>;
|
||||||
@@ -78,33 +76,31 @@ class core_factory {
|
|||||||
core_factory& operator=(const core_factory&) = delete;
|
core_factory& operator=(const core_factory&) = delete;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static core_factory & instance() { static core_factory bf; return bf; }
|
static core_factory& instance() {
|
||||||
|
static core_factory bf;
|
||||||
bool register_creator(const std::string &, create_fn const&);
|
return bf;
|
||||||
|
|
||||||
base_t create(const std::string &, unsigned gdb_port=0, void* init_data=nullptr) const;
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
inline bool core_factory::register_creator(const std::string & className, create_fn const& fn) {
|
bool register_creator(const std::string& className, create_fn const& fn) {
|
||||||
registry[className] = fn;
|
registry[className] = fn;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline core_factory::base_t core_factory::create(const std::string &className, unsigned gdb_port, void* data) const {
|
base_t create(std::string const& className, unsigned gdb_port = 0, void* init_data = nullptr) const {
|
||||||
registry_t::const_iterator regEntry = registry.find(className);
|
registry_t::const_iterator regEntry = registry.find(className);
|
||||||
if(regEntry != registry.end())
|
if(regEntry != registry.end())
|
||||||
return regEntry->second(gdb_port, data);
|
return regEntry->second(gdb_port, init_data);
|
||||||
return {nullptr, nullptr};
|
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_ */
|
#endif /* _ISS_FACTORY_H_ */
|
||||||
|
|||||||
8
src/iss/plugin/README.md
Normal file
8
src/iss/plugin/README.md
Normal file
@@ -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).
|
||||||
@@ -33,68 +33,60 @@
|
|||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
#include "cycle_estimate.h"
|
#include "cycle_estimate.h"
|
||||||
|
#include <iss/plugin/calculator.h>
|
||||||
|
#include <yaml-cpp/yaml.h>
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
#include <iss/arch_if.h>
|
#include <iss/arch_if.h>
|
||||||
#include <util/logging.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;
|
using namespace std;
|
||||||
|
|
||||||
iss::plugin::cycle_estimate::cycle_estimate(string const& config_file_name)
|
iss::plugin::cycle_estimate::cycle_estimate(string const& config_file_name)
|
||||||
: instr_if(nullptr)
|
: instr_if(nullptr)
|
||||||
, config_file_name(config_file_name)
|
, config_file_name(config_file_name) {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
iss::plugin::cycle_estimate::~cycle_estimate() {
|
iss::plugin::cycle_estimate::~cycle_estimate() = default;
|
||||||
}
|
|
||||||
|
|
||||||
bool iss::plugin::cycle_estimate::registration(const char* const version, vm_if& vm) {
|
bool iss::plugin::cycle_estimate::registration(const char* const version, vm_if& vm) {
|
||||||
instr_if = vm.get_arch()->get_instrumentation_if();
|
instr_if = vm.get_arch()->get_instrumentation_if();
|
||||||
if(!instr_if) return false;
|
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();
|
const string core_name = instr_if->core_type_name();
|
||||||
if(config_file_name.length() > 0) {
|
if(config_file_name.length() > 0) {
|
||||||
ifstream is(config_file_name);
|
std::ifstream is(config_file_name);
|
||||||
if(is.is_open()) {
|
if(is.is_open()) {
|
||||||
try {
|
try {
|
||||||
IStreamWrapper isw(is);
|
auto root = YAML::LoadAll(is);
|
||||||
Document d;
|
if(root.size() != 1) {
|
||||||
ParseResult ok = d.ParseStream(isw);
|
LOG(ERR) << "Too many root nodes in YAML file " << config_file_name;
|
||||||
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");
|
|
||||||
}
|
}
|
||||||
|
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 {
|
} else {
|
||||||
LOG(ERR)<<"plugin cycle_estimate: could not find an entry for "<<core_name<<" in JSON file"<<endl;
|
try {
|
||||||
return false;
|
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>());
|
||||||
}
|
}
|
||||||
} 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) {
|
}
|
||||||
|
}
|
||||||
|
} catch(YAML::ParserException& e) {
|
||||||
LOG(ERR) << "Could not parse input file " << config_file_name << ", reason: " << e.what();
|
LOG(ERR) << "Could not parse input file " << config_file_name << ", reason: " << e.what();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -104,15 +96,19 @@ bool iss::plugin::cycle_estimate::registration(const char* const version, vm_if&
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void iss::plugin::cycle_estimate::callback(instr_info_t instr_info) {
|
void iss::plugin::cycle_estimate::callback(instr_info_t instr_info) {
|
||||||
assert(instr_if && "No instrumentation interface available but callback executed");
|
size_t instr_id = instr_info.instr_id;
|
||||||
auto entry = delays[instr_info.instr_id];
|
auto& entry = instr_id < delays.size() ? delays[instr_id] : illegal_desc;
|
||||||
bool taken = instr_if->is_branch_taken();
|
if(instr_info.phase_id == PRE_SYNC) {
|
||||||
if (taken && (entry.taken > 1))
|
if(entry.f)
|
||||||
instr_if->update_last_instr_cycles(entry.taken);
|
current_delay = entry.f(instr_if->get_instr_word());
|
||||||
else if (entry.not_taken > 1)
|
} else {
|
||||||
instr_if->update_last_instr_cycles(entry.not_taken);
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,6 +37,7 @@
|
|||||||
|
|
||||||
#include "iss/instrumentation_if.h"
|
#include "iss/instrumentation_if.h"
|
||||||
#include "iss/vm_plugin.h"
|
#include "iss/vm_plugin.h"
|
||||||
|
#include <functional>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -46,18 +47,13 @@ namespace iss {
|
|||||||
namespace plugin {
|
namespace plugin {
|
||||||
|
|
||||||
class cycle_estimate : public vm_plugin {
|
class cycle_estimate : public vm_plugin {
|
||||||
BEGIN_BF_DECL(instr_desc, uint32_t)
|
struct instr_desc {
|
||||||
BF_FIELD(taken, 24, 8)
|
size_t size{0};
|
||||||
BF_FIELD(not_taken, 16, 8)
|
bool is_branch{false};
|
||||||
BF_FIELD(is_branch, 8, 8)
|
unsigned not_taken{1};
|
||||||
BF_FIELD(size, 0, 8)
|
unsigned taken{1};
|
||||||
instr_desc(uint32_t size, uint32_t taken, uint32_t not_taken, bool branch): instr_desc() {
|
std::function<unsigned(uint64_t)> f;
|
||||||
this->size=size;
|
};
|
||||||
this->taken=taken;
|
|
||||||
this->not_taken=not_taken;
|
|
||||||
this->is_branch=branch;
|
|
||||||
}
|
|
||||||
END_BF_DECL();
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
cycle_estimate() = delete;
|
cycle_estimate() = delete;
|
||||||
@@ -76,13 +72,16 @@ public:
|
|||||||
|
|
||||||
bool registration(const char* const version, vm_if& arch) override;
|
bool registration(const char* const version, vm_if& arch) override;
|
||||||
|
|
||||||
sync_type get_sync() override { return POST_SYNC; };
|
sync_type get_sync() override { return ALL_SYNC; };
|
||||||
|
|
||||||
void callback(instr_info_t instr_info) override;
|
void callback(instr_info_t instr_info) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
iss::instrumentation_if *instr_if;
|
iss::instrumentation_if* instr_if{nullptr};
|
||||||
|
uint32_t* reg_base_ptr{nullptr};
|
||||||
|
instr_desc illegal_desc{};
|
||||||
std::vector<instr_desc> delays;
|
std::vector<instr_desc> delays;
|
||||||
|
unsigned current_delay{0};
|
||||||
struct pair_hash {
|
struct pair_hash {
|
||||||
size_t operator()(const std::pair<uint64_t, uint64_t>& p) const {
|
size_t operator()(const std::pair<uint64_t, uint64_t>& p) const {
|
||||||
std::hash<uint64_t> hash;
|
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::unordered_map<std::pair<uint64_t, uint64_t>, uint64_t, pair_hash> blocks;
|
||||||
std::string config_file_name;
|
std::string config_file_name;
|
||||||
};
|
};
|
||||||
}
|
} // namespace plugin
|
||||||
}
|
} // namespace iss
|
||||||
|
|
||||||
#endif /* _ISS_PLUGIN_CYCLE_ESTIMATE_H_ */
|
#endif /* _ISS_PLUGIN_CYCLE_ESTIMATE_H_ */
|
||||||
|
|||||||
@@ -34,18 +34,41 @@
|
|||||||
|
|
||||||
#include "instruction_count.h"
|
#include "instruction_count.h"
|
||||||
#include <iss/instrumentation_if.h>
|
#include <iss/instrumentation_if.h>
|
||||||
|
#include <yaml-cpp/yaml.h>
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
#include <iss/arch_if.h>
|
#include <iss/arch_if.h>
|
||||||
#include <util/logging.h>
|
#include <util/logging.h>
|
||||||
#include <fstream>
|
|
||||||
|
|
||||||
iss::plugin::instruction_count::instruction_count(std::string config_file_name) {
|
iss::plugin::instruction_count::instruction_count(std::string config_file_name) {
|
||||||
if(config_file_name.length() > 0) {
|
if(config_file_name.length() > 0) {
|
||||||
std::ifstream is(config_file_name);
|
std::ifstream is(config_file_name);
|
||||||
if(is.is_open()) {
|
if(is.is_open()) {
|
||||||
try {
|
try {
|
||||||
is >> root;
|
auto root = YAML::LoadAll(is);
|
||||||
} catch (Json::RuntimeError &e) {
|
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();
|
LOG(ERR) << "Could not parse input file " << config_file_name << ", reason: " << e.what();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -57,7 +80,7 @@ iss::plugin::instruction_count::instruction_count(std::string config_file_name)
|
|||||||
iss::plugin::instruction_count::~instruction_count() {
|
iss::plugin::instruction_count::~instruction_count() {
|
||||||
size_t idx = 0;
|
size_t idx = 0;
|
||||||
for(auto it : delays) {
|
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];
|
LOG(INFO) << it.instr_name << ";" << rep_counts[idx];
|
||||||
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) {
|
bool iss::plugin::instruction_count::registration(const char* const version, vm_if& vm) {
|
||||||
auto instr_if = vm.get_arch()->get_instrumentation_if();
|
auto instr_if = vm.get_arch()->get_instrumentation_if();
|
||||||
if(!instr_if) return false;
|
if(!instr_if)
|
||||||
const std::string core_name = instr_if->core_type_name();
|
return false;
|
||||||
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;
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void iss::plugin::instruction_count::callback(instr_info_t instr_info) {
|
void iss::plugin::instruction_count::callback(instr_info_t instr_info) { rep_counts[instr_info.instr_id]++; }
|
||||||
rep_counts[instr_info.instr_id]++;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -36,8 +36,8 @@
|
|||||||
#define _ISS_PLUGIN_INSTRUCTION_COUNTER_H_
|
#define _ISS_PLUGIN_INSTRUCTION_COUNTER_H_
|
||||||
|
|
||||||
#include <iss/vm_plugin.h>
|
#include <iss/vm_plugin.h>
|
||||||
#include <json/json.h>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace iss {
|
namespace iss {
|
||||||
namespace plugin {
|
namespace plugin {
|
||||||
@@ -72,11 +72,10 @@ public:
|
|||||||
void callback(instr_info_t) override;
|
void callback(instr_info_t) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Json::Value root;
|
|
||||||
std::vector<instr_delay> delays;
|
std::vector<instr_delay> delays;
|
||||||
std::vector<uint64_t> rep_counts;
|
std::vector<uint64_t> rep_counts;
|
||||||
};
|
};
|
||||||
}
|
} // namespace plugin
|
||||||
}
|
} // namespace iss
|
||||||
|
|
||||||
#endif /* _ISS_PLUGIN_INSTRUCTION_COUNTER_H_ */
|
#endif /* _ISS_PLUGIN_INSTRUCTION_COUNTER_H_ */
|
||||||
|
|||||||
@@ -1,214 +0,0 @@
|
|||||||
/*******************************************************************************
|
|
||||||
* Copyright (C) 2017 - 2023, MINRES Technologies GmbH
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
*
|
|
||||||
* 1. Redistributions of source code must retain the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer.
|
|
||||||
*
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer in the documentation
|
|
||||||
* and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* 3. Neither the name of the copyright holder nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
|
||||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
||||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
||||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
* POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* Contributors:
|
|
||||||
* alex.com - initial implementation
|
|
||||||
******************************************************************************/
|
|
||||||
|
|
||||||
#include <iss/arch_if.h>
|
|
||||||
#include <iss/plugin/pctrace.h>
|
|
||||||
#include <util/logging.h>
|
|
||||||
#include <util/ities.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>
|
|
||||||
#ifdef WITH_LZ4
|
|
||||||
#include <lz4frame.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace iss {
|
|
||||||
namespace plugin {
|
|
||||||
|
|
||||||
using namespace rapidjson;
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
#ifdef WITH_LZ4
|
|
||||||
class lz4compress_steambuf: public std::streambuf {
|
|
||||||
public:
|
|
||||||
lz4compress_steambuf(const lz4compress_steambuf&) = delete;
|
|
||||||
lz4compress_steambuf& operator=(const lz4compress_steambuf&) = delete;
|
|
||||||
lz4compress_steambuf(std::ostream &sink, size_t buf_size)
|
|
||||||
: sink(sink)
|
|
||||||
, src_buf(buf_size)
|
|
||||||
, dest_buf(LZ4F_compressBound(buf_size, nullptr))
|
|
||||||
{
|
|
||||||
auto errCode = LZ4F_createCompressionContext(&ctx, LZ4F_VERSION);
|
|
||||||
if (LZ4F_isError(errCode) != 0)
|
|
||||||
throw std::runtime_error(std::string("Failed to create LZ4 context: ") + LZ4F_getErrorName(errCode));
|
|
||||||
size_t ret = LZ4F_compressBegin(ctx, &dest_buf.front(), dest_buf.capacity(), nullptr);
|
|
||||||
if (LZ4F_isError(ret) != 0)
|
|
||||||
throw std::runtime_error(std::string("Failed to start LZ4 compression: ") + LZ4F_getErrorName(ret));
|
|
||||||
setp(src_buf.data(), src_buf.data() + src_buf.size() - 1);
|
|
||||||
sink.write(dest_buf.data(), ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
~lz4compress_steambuf() {
|
|
||||||
close();
|
|
||||||
}
|
|
||||||
|
|
||||||
void close() {
|
|
||||||
if (closed)
|
|
||||||
return;
|
|
||||||
sync();
|
|
||||||
auto ret = LZ4F_compressEnd(ctx, dest_buf.data(), dest_buf.capacity(), nullptr);
|
|
||||||
if (LZ4F_isError(ret) != 0)
|
|
||||||
throw std::runtime_error(std::string("Failed to finish LZ4 compression: ") + LZ4F_getErrorName(ret));
|
|
||||||
sink.write(dest_buf.data(), ret);
|
|
||||||
LZ4F_freeCompressionContext(ctx);
|
|
||||||
closed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
int_type overflow(int_type ch) override {
|
|
||||||
compress_and_write();
|
|
||||||
*pptr() = static_cast<char_type>(ch);
|
|
||||||
pbump(1);
|
|
||||||
return ch;
|
|
||||||
}
|
|
||||||
|
|
||||||
int_type sync() override {
|
|
||||||
compress_and_write();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void compress_and_write() {
|
|
||||||
if (closed)
|
|
||||||
throw std::runtime_error("Cannot write to closed stream");
|
|
||||||
if(auto orig_size = pptr() - pbase()){
|
|
||||||
auto ret = LZ4F_compressUpdate(ctx, dest_buf.data(), dest_buf.capacity(), pbase(), orig_size, nullptr);
|
|
||||||
if (LZ4F_isError(ret) != 0)
|
|
||||||
throw std::runtime_error(std::string("LZ4 compression failed: ") + LZ4F_getErrorName(ret));
|
|
||||||
if(ret) sink.write(dest_buf.data(), ret);
|
|
||||||
pbump(-orig_size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::ostream &sink;
|
|
||||||
std::vector<char> src_buf;
|
|
||||||
std::vector<char> dest_buf;
|
|
||||||
LZ4F_compressionContext_t ctx{ nullptr };
|
|
||||||
bool closed{ false };
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
pctrace::pctrace(std::string const &filename)
|
|
||||||
: instr_if(nullptr)
|
|
||||||
, filename(filename)
|
|
||||||
, output("output.trc")
|
|
||||||
#ifdef WITH_LZ4
|
|
||||||
, strbuf(new lz4compress_steambuf(output, 4096))
|
|
||||||
, ostr(strbuf.get())
|
|
||||||
#endif
|
|
||||||
{ }
|
|
||||||
|
|
||||||
pctrace::~pctrace() { }
|
|
||||||
|
|
||||||
bool pctrace::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;
|
|
||||||
}
|
|
||||||
|
|
||||||
void pctrace::callback(instr_info_t iinfo) {
|
|
||||||
auto delay = 0;
|
|
||||||
size_t id = iinfo.instr_id;
|
|
||||||
auto entry = delays[id];
|
|
||||||
auto instr = instr_if->get_instr_word();
|
|
||||||
auto call = id==65 || id ==86 || ((id==2 || id==3) && bit_sub<7,5>(instr)!=0) ;//not taking care of tail calls (jalr with loading x6)
|
|
||||||
bool taken = instr_if->is_branch_taken();
|
|
||||||
bool compressed = (instr&0x3)!=0x3;
|
|
||||||
if (taken) {
|
|
||||||
delay = entry.taken;
|
|
||||||
if(entry.taken > 1)
|
|
||||||
instr_if->update_last_instr_cycles(entry.taken);
|
|
||||||
} else {
|
|
||||||
delay = entry.not_taken;
|
|
||||||
if (entry.not_taken > 1)
|
|
||||||
instr_if->update_last_instr_cycles(entry.not_taken);
|
|
||||||
}
|
|
||||||
#ifndef WITH_LZ4
|
|
||||||
output<<std::hex <<"0x" << instr_if->get_pc() <<"," << delay <<"," << call<<","<<(compressed?2:4) <<"\n";
|
|
||||||
#else
|
|
||||||
auto rdbuf=ostr.rdbuf();
|
|
||||||
ostr<<std::hex <<"0x" << instr_if->get_pc() <<"," << delay <<"," << call<<","<<(compressed?2:4) <<"\n";
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
41
src/main.cpp
41
src/main.cpp
@@ -30,21 +30,20 @@
|
|||||||
*
|
*
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <vector>
|
|
||||||
#include <array>
|
#include <array>
|
||||||
|
#include <iostream>
|
||||||
#include <iss/factory.h>
|
#include <iss/factory.h>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "iss/arch/tgc_mapper.h"
|
||||||
#include <boost/lexical_cast.hpp>
|
#include <boost/lexical_cast.hpp>
|
||||||
#include <boost/program_options.hpp>
|
#include <boost/program_options.hpp>
|
||||||
#include "iss/arch/tgc_mapper.h"
|
|
||||||
#ifdef WITH_LLVM
|
#ifdef WITH_LLVM
|
||||||
#include <iss/llvm/jit_helper.h>
|
#include <iss/llvm/jit_init.h>
|
||||||
#endif
|
#endif
|
||||||
#include <iss/log_categories.h>
|
|
||||||
#include "iss/plugin/cycle_estimate.h"
|
#include "iss/plugin/cycle_estimate.h"
|
||||||
#include "iss/plugin/instruction_count.h"
|
#include "iss/plugin/instruction_count.h"
|
||||||
#include "iss/plugin/pctrace.h"
|
#include <iss/log_categories.h>
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
#include <iss/plugin/loader.h>
|
#include <iss/plugin/loader.h>
|
||||||
#endif
|
#endif
|
||||||
@@ -74,14 +73,14 @@ int main(int argc, char *argv[]) {
|
|||||||
("mem,m", po::value<std::string>(), "the memory input file")
|
("mem,m", po::value<std::string>(), "the memory input file")
|
||||||
("plugin,p", po::value<std::vector<std::string>>(), "plugin to activate")
|
("plugin,p", po::value<std::vector<std::string>>(), "plugin to activate")
|
||||||
("backend", po::value<std::string>()->default_value("interp"), "the ISS backend to use, options are: interp, tcc")
|
("backend", po::value<std::string>()->default_value("interp"), "the ISS backend to use, options are: interp, tcc")
|
||||||
("isa", po::value<std::string>()->default_value("tgc_c"), "isa to use for simulation");
|
("isa", po::value<std::string>()->default_value("tgc5c"), "core or isa name to use for simulation, use '?' to get list");
|
||||||
// clang-format on
|
// clang-format on
|
||||||
auto parsed = po::command_line_parser(argc, argv).options(desc).allow_unregistered().run();
|
auto parsed = po::command_line_parser(argc, argv).options(desc).allow_unregistered().run();
|
||||||
try {
|
try {
|
||||||
po::store(parsed, clim); // can throw
|
po::store(parsed, clim); // can throw
|
||||||
// --help option
|
// --help option
|
||||||
if(clim.count("help")) {
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
po::notify(clim); // throws on error, so do after help in case
|
po::notify(clim); // throws on error, so do after help in case
|
||||||
@@ -119,13 +118,15 @@ int main(int argc, char *argv[]) {
|
|||||||
iss::cpu_ptr cpu{nullptr};
|
iss::cpu_ptr cpu{nullptr};
|
||||||
std::string isa_opt(clim["isa"].as<std::string>());
|
std::string isa_opt(clim["isa"].as<std::string>());
|
||||||
if(isa_opt.size() == 0 || isa_opt == "?") {
|
if(isa_opt.size() == 0 || isa_opt == "?") {
|
||||||
std::cout<<"Available cores: "<<util::join(f.get_names(), ", ")<<std::endl;
|
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;
|
return 0;
|
||||||
} else if(isa_opt.find('|') != std::string::npos) {
|
} 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>());
|
std::tie(cpu, vm) = f.create(isa_opt + "|" + clim["backend"].as<std::string>(), clim["gdb-port"].as<unsigned>());
|
||||||
} else {
|
} else {
|
||||||
auto base_isa = isa_opt.substr(0, 5);
|
auto base_isa = isa_opt.substr(0, 5);
|
||||||
if(base_isa=="tgc_d" || base_isa=="tgc_e") {
|
if(base_isa == "tgc5d" || base_isa == "tgc5e") {
|
||||||
isa_opt += "|mu_p_clic_pmp|" + clim["backend"].as<std::string>();
|
isa_opt += "|mu_p_clic_pmp|" + clim["backend"].as<std::string>();
|
||||||
} else {
|
} else {
|
||||||
isa_opt += "|m_p|" + clim["backend"].as<std::string>();
|
isa_opt += "|m_p|" + clim["backend"].as<std::string>();
|
||||||
@@ -149,6 +150,7 @@ int main(int argc, char *argv[]) {
|
|||||||
plugin_name = opt_val.substr(0, found);
|
plugin_name = opt_val.substr(0, found);
|
||||||
arg = 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") {
|
if(plugin_name == "ic") {
|
||||||
auto* ic_plugin = new iss::plugin::instruction_count(arg);
|
auto* ic_plugin = new iss::plugin::instruction_count(arg);
|
||||||
vm->register_plugin(*ic_plugin);
|
vm->register_plugin(*ic_plugin);
|
||||||
@@ -157,12 +159,10 @@ int main(int argc, char *argv[]) {
|
|||||||
auto* ce_plugin = new iss::plugin::cycle_estimate(arg);
|
auto* ce_plugin = new iss::plugin::cycle_estimate(arg);
|
||||||
vm->register_plugin(*ce_plugin);
|
vm->register_plugin(*ce_plugin);
|
||||||
plugin_list.push_back(ce_plugin);
|
plugin_list.push_back(ce_plugin);
|
||||||
} else if (plugin_name == "pctrace") {
|
} else
|
||||||
auto *plugin = new iss::plugin::pctrace(arg);
|
#endif
|
||||||
vm->register_plugin(*plugin);
|
{
|
||||||
plugin_list.push_back(plugin);
|
#if !defined(WIN32)
|
||||||
} else {
|
|
||||||
#ifndef WIN32
|
|
||||||
std::vector<char const*> a{};
|
std::vector<char const*> a{};
|
||||||
if(arg.length())
|
if(arg.length())
|
||||||
a.push_back({arg.c_str()});
|
a.push_back({arg.c_str()});
|
||||||
@@ -196,11 +196,13 @@ int main(int argc, char *argv[]) {
|
|||||||
if(clim.count("elf"))
|
if(clim.count("elf"))
|
||||||
for(std::string input : clim["elf"].as<std::vector<std::string>>()) {
|
for(std::string input : clim["elf"].as<std::vector<std::string>>()) {
|
||||||
auto start_addr = vm->get_arch()->load_file(input);
|
auto start_addr = vm->get_arch()->load_file(input);
|
||||||
if (start_addr.second) start_address = start_addr.first;
|
if(start_addr.second)
|
||||||
|
start_address = start_addr.first;
|
||||||
}
|
}
|
||||||
for(std::string input : args) {
|
for(std::string input : args) {
|
||||||
auto start_addr = vm->get_arch()->load_file(input); // treat remaining arguments as elf files
|
auto start_addr = vm->get_arch()->load_file(input); // treat remaining arguments as elf files
|
||||||
if (start_addr.second) start_address = start_addr.first;
|
if(start_addr.second)
|
||||||
|
start_address = start_addr.first;
|
||||||
}
|
}
|
||||||
if(clim.count("reset")) {
|
if(clim.count("reset")) {
|
||||||
auto str = clim["reset"].as<std::string>();
|
auto str = clim["reset"].as<std::string>();
|
||||||
@@ -210,8 +212,7 @@ int main(int argc, char *argv[]) {
|
|||||||
auto cycles = clim["instructions"].as<uint64_t>();
|
auto cycles = clim["instructions"].as<uint64_t>();
|
||||||
res = vm->start(cycles, dump);
|
res = vm->start(cycles, dump);
|
||||||
} catch(std::exception& e) {
|
} catch(std::exception& e) {
|
||||||
LOG(ERR) << "Unhandled Exception reached the top of main: " << e.what() << ", application will now exit"
|
LOG(ERR) << "Unhandled Exception reached the top of main: " << e.what() << ", application will now exit" << std::endl;
|
||||||
<< std::endl;
|
|
||||||
res = 2;
|
res = 2;
|
||||||
}
|
}
|
||||||
// cleanup to let plugins report of needed
|
// cleanup to let plugins report of needed
|
||||||
|
|||||||
@@ -37,25 +37,28 @@
|
|||||||
#include <iss/debugger/target_adapter_if.h>
|
#include <iss/debugger/target_adapter_if.h>
|
||||||
#include <iss/iss.h>
|
#include <iss/iss.h>
|
||||||
#include <iss/vm_types.h>
|
#include <iss/vm_types.h>
|
||||||
|
#include "iss_factory.h"
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
#include <iss/plugin/loader.h>
|
#include <iss/plugin/loader.h>
|
||||||
#endif
|
#endif
|
||||||
#include "core_complex.h"
|
#include "sc_core_adapter_if.h"
|
||||||
#include <iss/arch/tgc_mapper.h>
|
#include <iss/arch/tgc_mapper.h>
|
||||||
#include <scc/report.h>
|
#include <scc/report.h>
|
||||||
#include <util/ities.h>
|
#include <util/ities.h>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <array>
|
#include <array>
|
||||||
|
#include <numeric>
|
||||||
#include <iss/plugin/cycle_estimate.h>
|
#include <iss/plugin/cycle_estimate.h>
|
||||||
#include <iss/plugin/instruction_count.h>
|
#include <iss/plugin/instruction_count.h>
|
||||||
#include <iss/plugin/pctrace.h>
|
|
||||||
|
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
#define STR(X) #X
|
#define STR(X) #X
|
||||||
#define CREATE_CORE(CN) \
|
#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
|
#ifdef HAS_SCV
|
||||||
#include <scv.h>
|
#include <scv.h>
|
||||||
@@ -85,138 +88,10 @@ using namespace sc_core;
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
iss::debugger::encoder_decoder encdec;
|
iss::debugger::encoder_decoder encdec;
|
||||||
|
|
||||||
std::array<const char, 4> lvl = {{'U', 'S', 'H', 'M'}};
|
std::array<const char, 4> lvl = {{'U', 'S', 'H', 'M'}};
|
||||||
}
|
} // namespace
|
||||||
|
|
||||||
template<typename PLAT>
|
int cmd_sysc(int argc, char* argv[], debugger::out_func of, debugger::data_func df, debugger::target_adapter_if* tgt_adapter) {
|
||||||
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->instr_if.get_total_cycles());
|
|
||||||
}
|
|
||||||
|
|
||||||
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, is_fetch(addr.access)) ? 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";
|
|
||||||
while(this->reg.pending_trap == 0 && (this->csr[arch::mip] & this->csr[arch::mie]) == 0) {
|
|
||||||
sc_core::wait(wfi_evt);
|
|
||||||
}
|
|
||||||
PLAT::wait_until(flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
void local_irq(short id, bool value) {
|
|
||||||
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[arch::mip] |= mask;
|
|
||||||
wfi_evt.notify();
|
|
||||||
} else
|
|
||||||
this->csr[arch::mip] &= ~mask;
|
|
||||||
this->check_interrupt();
|
|
||||||
if(value)
|
|
||||||
SCCTRACE(owner->name()) << "Triggering interrupt " << id << " Pending trap: " << this->reg.pending_trap;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
core_complex *const owner;
|
|
||||||
sc_event wfi_evt;
|
|
||||||
};
|
|
||||||
|
|
||||||
int cmd_sysc(int argc, char *argv[], debugger::out_func of, debugger::data_func df,
|
|
||||||
debugger::target_adapter_if *tgt_adapter) {
|
|
||||||
if(argc > 1) {
|
if(argc > 1) {
|
||||||
if(strcasecmp(argv[1], "print_time") == 0) {
|
if(strcasecmp(argv[1], "print_time") == 0) {
|
||||||
std::string t = sc_time_stamp().to_string();
|
std::string t = sc_time_stamp().to_string();
|
||||||
@@ -250,11 +125,15 @@ using vm_ptr= std::unique_ptr<iss::vm_if>;
|
|||||||
|
|
||||||
class core_wrapper {
|
class core_wrapper {
|
||||||
public:
|
public:
|
||||||
core_wrapper(core_complex *owner) : owner(owner) { }
|
core_wrapper(core_complex* owner)
|
||||||
|
: owner(owner) {}
|
||||||
|
|
||||||
void reset(uint64_t addr) { vm->reset(addr); }
|
void reset(uint64_t addr) { vm->reset(addr); }
|
||||||
inline void start(){vm->start();}
|
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){ return cpu->load_file(name);};
|
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<unsigned(void)> get_mode;
|
||||||
std::function<uint64_t(void)> get_state;
|
std::function<uint64_t(void)> get_state;
|
||||||
@@ -262,58 +141,49 @@ public:
|
|||||||
std::function<void(bool)> set_interrupt_execution;
|
std::function<void(bool)> set_interrupt_execution;
|
||||||
std::function<void(short, bool)> local_irq;
|
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) {
|
void create_cpu(std::string const& type, std::string const& backend, unsigned gdb_port, uint32_t hart_id) {
|
||||||
CREATE_CORE(tgc_c)
|
auto& f = sysc::iss_factory::instance();
|
||||||
#ifdef CORE_TGC_B
|
if(type.size() == 0 || type == "?") {
|
||||||
CREATE_CORE(tgc_b)
|
std::cout << "Available cores: " << util::join(f.get_names(), ", ") << std::endl;
|
||||||
#endif
|
sc_core::sc_stop();
|
||||||
#ifdef CORE_TGC_D
|
} else if(type.find('|') != std::string::npos) {
|
||||||
CREATE_CORE(tgc_d)
|
std::tie(cpu, vm) = f.create(type + "|" + backend);
|
||||||
#endif
|
} else {
|
||||||
#ifdef CORE_TGC_D_XRB_MAC
|
auto base_isa = type.substr(0, 5);
|
||||||
CREATE_CORE(tgc_d_xrb_mac)
|
if(base_isa == "tgc5d" || base_isa == "tgc5e") {
|
||||||
#endif
|
std::tie(cpu, vm) = f.create(type + "|mu_p_clic_pmp|" + backend, gdb_port, owner);
|
||||||
#ifdef CORE_TGC_D_XRB_NN
|
} else {
|
||||||
CREATE_CORE(tgc_d_xrb_nn)
|
std::tie(cpu, vm) = f.create(type + "|m_p|" + backend, gdb_port, owner);
|
||||||
#endif
|
|
||||||
{
|
|
||||||
LOG(ERR) << "Illegal argument value for core type: " << type << std::endl;
|
|
||||||
}
|
}
|
||||||
auto *srv = debugger::server<debugger::gdb_session>::get();
|
}
|
||||||
if (srv) tgt_adapter = srv->get_target();
|
if(!cpu) {
|
||||||
if (tgt_adapter)
|
SCCFATAL() << "Could not create cpu for isa " << type << " and backend " << backend;
|
||||||
tgt_adapter->add_custom_command(
|
}
|
||||||
{"sysc", [this](int argc, char *argv[], debugger::out_func of,
|
if(!vm) {
|
||||||
debugger::data_func df) -> int { return cmd_sysc(argc, argv, of, df, tgt_adapter); },
|
SCCFATAL() << "Could not create vm for isa " << type << " and backend " << backend;
|
||||||
"SystemC sub-commands: break <time>, print_time"});
|
}
|
||||||
|
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;
|
core_complex* const owner;
|
||||||
vm_ptr vm{nullptr};
|
vm_ptr vm{nullptr};
|
||||||
cpu_ptr cpu{nullptr};
|
sc_cpu_ptr cpu{nullptr};
|
||||||
iss::debugger::target_adapter_if* tgt_adapter{nullptr};
|
iss::debugger::target_adapter_if* tgt_adapter{nullptr};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -333,8 +203,7 @@ core_complex::core_complex(sc_module_name const& name)
|
|||||||
: sc_module(name)
|
: sc_module(name)
|
||||||
, fetch_lut(tlm_dmi_ext())
|
, fetch_lut(tlm_dmi_ext())
|
||||||
, read_lut(tlm_dmi_ext())
|
, read_lut(tlm_dmi_ext())
|
||||||
, write_lut(tlm_dmi_ext())
|
, write_lut(tlm_dmi_ext()) {
|
||||||
{
|
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -417,10 +286,6 @@ void core_complex::before_end_of_elaboration() {
|
|||||||
auto* plugin = new iss::plugin::cycle_estimate(filename);
|
auto* plugin = new iss::plugin::cycle_estimate(filename);
|
||||||
cpu->vm->register_plugin(*plugin);
|
cpu->vm->register_plugin(*plugin);
|
||||||
plugin_list.push_back(plugin);
|
plugin_list.push_back(plugin);
|
||||||
} else if (plugin_name == "pctrace") {
|
|
||||||
auto *plugin = new iss::plugin::pctrace(filename);
|
|
||||||
cpu->vm->register_plugin(*plugin);
|
|
||||||
plugin_list.push_back(plugin);
|
|
||||||
} else {
|
} else {
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
std::array<char const*, 1> a{{filename.c_str()}};
|
std::array<char const*, 1> a{{filename.c_str()}};
|
||||||
@@ -435,7 +300,6 @@ void core_complex::before_end_of_elaboration() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void core_complex::start_of_simulation() {
|
void core_complex::start_of_simulation() {
|
||||||
@@ -462,8 +326,10 @@ void core_complex::start_of_simulation() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool core_complex::disass_output(uint64_t pc, const std::string instr_str) {
|
bool core_complex::disass_output(uint64_t pc, const std::string instr_str) {
|
||||||
if (trc->m_db == nullptr) return false;
|
if(trc->m_db == nullptr)
|
||||||
if (trc->tr_handle.is_active()) trc->tr_handle.end_transaction();
|
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 = trc->instr_tr_handle->begin_transaction();
|
||||||
trc->tr_handle.record_attribute("PC", pc);
|
trc->tr_handle.record_attribute("PC", pc);
|
||||||
trc->tr_handle.record_attribute("INSTR", instr_str);
|
trc->tr_handle.record_attribute("INSTR", instr_str);
|
||||||
@@ -484,11 +350,13 @@ void core_complex::forward() {
|
|||||||
|
|
||||||
void core_complex::set_clock_period(sc_core::sc_time period) {
|
void core_complex::set_clock_period(sc_core::sc_time period) {
|
||||||
curr_clk = 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() {
|
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(3, sw_irq_i.read()); }
|
void core_complex::sw_irq_cb() { cpu->local_irq(3, sw_irq_i.read()); }
|
||||||
@@ -518,7 +386,7 @@ void core_complex::run() {
|
|||||||
}
|
}
|
||||||
quantum_keeper.reset();
|
quantum_keeper.reset();
|
||||||
cpu->set_interrupt_execution(false);
|
cpu->set_interrupt_execution(false);
|
||||||
cpu->start();
|
cpu->start(dump_ir);
|
||||||
} while(cpu->get_interrupt_execution());
|
} while(cpu->get_interrupt_execution());
|
||||||
sc_stop();
|
sc_stop();
|
||||||
}
|
}
|
||||||
@@ -529,7 +397,10 @@ bool core_complex::read_mem(uint64_t addr, unsigned length, uint8_t *const data,
|
|||||||
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();
|
auto offset = addr - lut_entry.get_start_address();
|
||||||
std::copy(lut_entry.get_dmi_ptr() + offset, lut_entry.get_dmi_ptr() + offset + length, data);
|
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;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
auto& sckt = is_fetch ? ibus : dbus;
|
auto& sckt = is_fetch ? ibus : dbus;
|
||||||
@@ -547,24 +418,29 @@ 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);
|
auto preExt = new tlm::scc::scv::tlm_recording_extension(trc->tr_handle, this);
|
||||||
gp.set_extension(preExt);
|
gp.set_extension(preExt);
|
||||||
}
|
}
|
||||||
sckt->b_transport(gp, delay);
|
auto pre_delay = delay;
|
||||||
auto incr = delay-quantum_keeper.get_local_time();
|
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)
|
if(is_fetch)
|
||||||
ibus_inc += incr;
|
ibus_inc += incr;
|
||||||
else
|
else
|
||||||
dbus_inc += incr;
|
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);
|
}
|
||||||
|
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) {
|
if(gp.get_response_status() != tlm::TLM_OK_RESPONSE) {
|
||||||
return false;
|
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_command(tlm::TLM_READ_COMMAND);
|
||||||
gp.set_address(addr);
|
gp.set_address(addr);
|
||||||
tlm_dmi_ext dmi_data;
|
tlm_dmi_ext dmi_data;
|
||||||
if(sckt->get_direct_mem_ptr(gp, dmi_data)) {
|
if(sckt->get_direct_mem_ptr(gp, dmi_data)) {
|
||||||
if(dmi_data.is_read_allowed())
|
if(dmi_data.is_read_allowed())
|
||||||
dmi_lut.addEntry(dmi_data, dmi_data.get_start_address(),
|
dmi_lut.addEntry(dmi_data, dmi_data.get_start_address(), dmi_data.get_end_address() - dmi_data.get_start_address() + 1);
|
||||||
dmi_data.get_end_address() - dmi_data.get_start_address() + 1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -573,11 +449,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) {
|
bool core_complex::write_mem(uint64_t addr, unsigned length, const uint8_t* const data) {
|
||||||
auto lut_entry = write_lut.getEntry(addr);
|
auto lut_entry = write_lut.getEntry(addr);
|
||||||
if (lut_entry.get_granted_access() != tlm::tlm_dmi::DMI_ACCESS_NONE &&
|
if(lut_entry.get_granted_access() != tlm::tlm_dmi::DMI_ACCESS_NONE && addr + length <= lut_entry.get_end_address() + 1) {
|
||||||
addr + length <= lut_entry.get_end_address() + 1) {
|
|
||||||
auto offset = addr - lut_entry.get_start_address();
|
auto offset = addr - lut_entry.get_start_address();
|
||||||
std::copy(data, data + length, lut_entry.get_dmi_ptr() + offset);
|
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;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
write_buf.resize(length);
|
write_buf.resize(length);
|
||||||
@@ -593,13 +468,18 @@ 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);
|
auto preExt = new tlm::scc::scv::tlm_recording_extension(trc->tr_handle, this);
|
||||||
gp.set_extension(preExt);
|
gp.set_extension(preExt);
|
||||||
}
|
}
|
||||||
|
auto pre_delay = delay;
|
||||||
dbus->b_transport(gp, delay);
|
dbus->b_transport(gp, delay);
|
||||||
dbus_inc+=delay-quantum_keeper.get_local_time();
|
if(pre_delay > delay)
|
||||||
SCCTRACE() << "[local time: "<<delay<<"]: finish write_mem(0x" << std::hex << addr << ") : 0x" << (length==4?*(uint32_t*)data:length==2?*(uint16_t*)data:(unsigned)*data);
|
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) {
|
if(gp.get_response_status() != tlm::TLM_OK_RESPONSE) {
|
||||||
return false;
|
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_command(tlm::TLM_READ_COMMAND);
|
||||||
gp.set_address(addr);
|
gp.set_address(addr);
|
||||||
tlm_dmi_ext dmi_data;
|
tlm_dmi_ext dmi_data;
|
||||||
@@ -634,5 +514,5 @@ bool core_complex::write_mem_dbg(uint64_t addr, unsigned length, const uint8_t *
|
|||||||
gp.set_streaming_width(length);
|
gp.set_streaming_width(length);
|
||||||
return dbus->transport_dbg(gp) == length;
|
return dbus->transport_dbg(gp) == length;
|
||||||
}
|
}
|
||||||
} /* namespace SiFive */
|
} /* namespace tgfs */
|
||||||
} /* namespace sysc */
|
} /* namespace sysc */
|
||||||
|
|||||||
@@ -33,10 +33,10 @@
|
|||||||
#ifndef _SYSC_CORE_COMPLEX_H_
|
#ifndef _SYSC_CORE_COMPLEX_H_
|
||||||
#define _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/tick2time.h>
|
||||||
|
#include <scc/traceable.h>
|
||||||
#include <scc/utilities.h>
|
#include <scc/utilities.h>
|
||||||
|
#include <tlm/scc/initiator_mixin.h>
|
||||||
#include <tlm/scc/scv/tlm_rec_initiator_socket.h>
|
#include <tlm/scc/scv/tlm_rec_initiator_socket.h>
|
||||||
#ifdef CWR_SYSTEMC
|
#ifdef CWR_SYSTEMC
|
||||||
#include <scmlinc/scml_property.h>
|
#include <scmlinc/scml_property.h>
|
||||||
@@ -45,10 +45,10 @@
|
|||||||
#include <cci_configuration>
|
#include <cci_configuration>
|
||||||
#define SOCKET_WIDTH scc::LT
|
#define SOCKET_WIDTH scc::LT
|
||||||
#endif
|
#endif
|
||||||
|
#include <memory>
|
||||||
#include <tlm>
|
#include <tlm>
|
||||||
#include <tlm_utils/tlm_quantumkeeper.h>
|
#include <tlm_utils/tlm_quantumkeeper.h>
|
||||||
#include <util/range_lut.h>
|
#include <util/range_lut.h>
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
namespace iss {
|
namespace iss {
|
||||||
class vm_plugin;
|
class vm_plugin;
|
||||||
@@ -58,8 +58,8 @@ namespace sysc {
|
|||||||
class tlm_dmi_ext : public tlm::tlm_dmi {
|
class tlm_dmi_ext : public tlm::tlm_dmi {
|
||||||
public:
|
public:
|
||||||
bool operator==(const tlm_dmi_ext& o) const {
|
bool operator==(const tlm_dmi_ext& o) const {
|
||||||
return this->get_granted_access() == o.get_granted_access() &&
|
return this->get_granted_access() == o.get_granted_access() && this->get_start_address() == o.get_start_address() &&
|
||||||
this->get_start_address() == o.get_start_address() && this->get_end_address() == o.get_end_address();
|
this->get_end_address() == o.get_end_address();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator!=(const tlm_dmi_ext& o) const { return !operator==(o); }
|
bool operator!=(const tlm_dmi_ext& o) const { return !operator==(o); }
|
||||||
@@ -94,9 +94,11 @@ public:
|
|||||||
|
|
||||||
cci::cci_param<bool> enable_disass{"enable_disass", false};
|
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<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"};
|
cci::cci_param<std::string> backend{"backend", "interp"};
|
||||||
|
|
||||||
@@ -119,9 +121,11 @@ public:
|
|||||||
|
|
||||||
scml_property<bool> enable_disass{"enable_disass", false};
|
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<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"};
|
scml_property<std::string> backend{"backend", "interp"};
|
||||||
|
|
||||||
@@ -139,7 +143,7 @@ public:
|
|||||||
, elf_file{"elf_file", ""}
|
, elf_file{"elf_file", ""}
|
||||||
, enable_disass{"enable_disass", false}
|
, enable_disass{"enable_disass", false}
|
||||||
, reset_address{"reset_address", 0ULL}
|
, reset_address{"reset_address", 0ULL}
|
||||||
, core_type{"core_type", "tgc_c"}
|
, core_type{"core_type", "tgc5c"}
|
||||||
, backend{"backend", "interp"}
|
, backend{"backend", "interp"}
|
||||||
, gdb_server_port{"gdb_server_port", 0}
|
, gdb_server_port{"gdb_server_port", 0}
|
||||||
, dump_ir{"dump_ir", false}
|
, dump_ir{"dump_ir", false}
|
||||||
@@ -147,8 +151,7 @@ public:
|
|||||||
, plugins{"plugins", ""}
|
, plugins{"plugins", ""}
|
||||||
, fetch_lut(tlm_dmi_ext())
|
, fetch_lut(tlm_dmi_ext())
|
||||||
, read_lut(tlm_dmi_ext())
|
, read_lut(tlm_dmi_ext())
|
||||||
, write_lut(tlm_dmi_ext())
|
, write_lut(tlm_dmi_ext()) {
|
||||||
{
|
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -156,17 +159,20 @@ public:
|
|||||||
|
|
||||||
~core_complex();
|
~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) {
|
inline void sync(uint64_t cycle) {
|
||||||
auto core_inc = curr_clk * (cycle - last_sync_cycle);
|
auto core_inc = curr_clk * (cycle - last_sync_cycle);
|
||||||
auto incr = std::max(core_inc, std::max(ibus_inc, dbus_inc));
|
quantum_keeper.inc(core_inc);
|
||||||
quantum_keeper.inc(incr);
|
|
||||||
if(quantum_keeper.need_sync()) {
|
if(quantum_keeper.need_sync()) {
|
||||||
wait(quantum_keeper.get_local_time());
|
wait(quantum_keeper.get_local_time());
|
||||||
quantum_keeper.reset();
|
quantum_keeper.reset();
|
||||||
}
|
}
|
||||||
last_sync_cycle = cycle;
|
last_sync_cycle = cycle;
|
||||||
ibus_inc = sc_core::SC_ZERO_TIME;
|
|
||||||
dbus_inc = sc_core::SC_ZERO_TIME;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool read_mem(uint64_t addr, unsigned length, uint8_t* const data, bool is_fetch);
|
bool read_mem(uint64_t addr, unsigned length, uint8_t* const data, bool is_fetch);
|
||||||
@@ -182,6 +188,7 @@ public:
|
|||||||
bool disass_output(uint64_t pc, const std::string instr);
|
bool disass_output(uint64_t pc, const std::string instr);
|
||||||
|
|
||||||
void set_clock_period(sc_core::sc_time period);
|
void set_clock_period(sc_core::sc_time period);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void before_end_of_elaboration() override;
|
void before_end_of_elaboration() override;
|
||||||
void start_of_simulation() override;
|
void start_of_simulation() override;
|
||||||
@@ -198,13 +205,13 @@ protected:
|
|||||||
std::vector<uint8_t> write_buf;
|
std::vector<uint8_t> write_buf;
|
||||||
core_wrapper* cpu{nullptr};
|
core_wrapper* cpu{nullptr};
|
||||||
sc_core::sc_signal<sc_core::sc_time> curr_clk;
|
sc_core::sc_signal<sc_core::sc_time> curr_clk;
|
||||||
sc_core::sc_time ibus_inc, dbus_inc;
|
uint64_t ibus_inc{0}, dbus_inc{0};
|
||||||
core_trace* trc{nullptr};
|
core_trace* trc{nullptr};
|
||||||
std::unique_ptr<scc::tick2time> t2t;
|
std::unique_ptr<scc::tick2time> t2t;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void init();
|
void init();
|
||||||
std::vector<iss::vm_plugin*> plugin_list;
|
std::vector<iss::vm_plugin*> plugin_list;
|
||||||
|
|
||||||
};
|
};
|
||||||
} /* namespace tgfs */
|
} /* namespace tgfs */
|
||||||
} /* namespace sysc */
|
} /* namespace sysc */
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Copyright (C) 2017 - 2023, MINRES Technologies GmbH
|
* Copyright (C) 2021 MINRES Technologies GmbH
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@@ -28,75 +28,63 @@
|
|||||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
* POSSIBILITY OF SUCH DAMAGE.
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* Contributors:
|
*******************************************************************************/
|
||||||
* eyck@minres.com - initial API and implementation
|
|
||||||
******************************************************************************/
|
|
||||||
|
|
||||||
#ifndef _ISS_PLUGIN_COV_H_
|
#ifndef _ISS_FACTORY_H_
|
||||||
#define _ISS_PLUGIN_COV_H_
|
#define _ISS_FACTORY_H_
|
||||||
|
|
||||||
#include <iss/vm_plugin.h>
|
#include "sc_core_adapter_if.h"
|
||||||
#include "iss/instrumentation_if.h"
|
#include <algorithm>
|
||||||
#include <json/json.h>
|
#include <functional>
|
||||||
|
#include <iss/iss.h>
|
||||||
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <fstream>
|
#include <unordered_map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace sysc {
|
||||||
|
|
||||||
namespace iss {
|
using sc_cpu_ptr = std::unique_ptr<sc_core_adapter_if>;
|
||||||
namespace plugin {
|
using vm_ptr = std::unique_ptr<iss::vm_if>;
|
||||||
class lz4compress_steambuf;
|
|
||||||
class pctrace : 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();
|
|
||||||
|
|
||||||
|
class iss_factory {
|
||||||
public:
|
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>;
|
||||||
|
|
||||||
pctrace(const pctrace &) = delete;
|
iss_factory() = default;
|
||||||
|
iss_factory(const iss_factory&) = delete;
|
||||||
|
iss_factory& operator=(const iss_factory&) = delete;
|
||||||
|
|
||||||
pctrace(const pctrace &&) = delete;
|
static iss_factory& instance() {
|
||||||
|
static iss_factory bf;
|
||||||
|
return bf;
|
||||||
|
}
|
||||||
|
|
||||||
pctrace(std::string const &);
|
bool register_creator(const std::string& className, create_fn const& fn) {
|
||||||
|
registry[className] = fn;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
virtual ~pctrace();
|
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};
|
||||||
|
}
|
||||||
|
|
||||||
pctrace &operator=(const pctrace &) = delete;
|
std::vector<std::string> get_names() {
|
||||||
|
std::vector<std::string> keys{registry.size()};
|
||||||
pctrace &operator=(const pctrace &&) = delete;
|
std::transform(std::begin(registry), std::end(registry), std::begin(keys),
|
||||||
|
[](std::pair<std::string, create_fn> const& p) { return p.first; });
|
||||||
bool registration(const char *const version, vm_if &arch) override;
|
return keys;
|
||||||
|
}
|
||||||
sync_type get_sync() override { return POST_SYNC; };
|
|
||||||
|
|
||||||
void callback(instr_info_t) override;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
iss::instrumentation_if *instr_if {nullptr};
|
registry_t registry;
|
||||||
std::ofstream output;
|
|
||||||
#ifdef WITH_LZ4
|
|
||||||
std::unique_ptr<lz4compress_steambuf> strbuf;
|
|
||||||
std::ostream ostr;
|
|
||||||
#endif
|
|
||||||
std::string filename;
|
|
||||||
std::vector<instr_desc> delays;
|
|
||||||
bool jumped{false}, first{true};
|
|
||||||
};
|
};
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* _ISS_PLUGIN_COV_H_ */
|
} // namespace sysc
|
||||||
|
|
||||||
|
#endif /* _ISS_FACTORY_H_ */
|
||||||
@@ -1,33 +1,110 @@
|
|||||||
/*
|
/*******************************************************************************
|
||||||
* register_tgc_c.cpp
|
* Copyright (C) 2023 MINRES Technologies GmbH
|
||||||
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Created on: Jul 5, 2023
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* Author: eyck
|
* 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/factory.h>
|
|
||||||
#include <iss/arch/tgc_c.h>
|
|
||||||
#include <iss/arch/riscv_hart_m_p.h>
|
#include <iss/arch/riscv_hart_m_p.h>
|
||||||
#include <iss/arch/riscv_hart_mu_p.h>
|
#include <iss/arch/riscv_hart_mu_p.h>
|
||||||
#include "sc_core_adapter.h"
|
#include "sc_core_adapter.h"
|
||||||
#include "core_complex.h"
|
#include "core_complex.h"
|
||||||
|
#include <array>
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
namespace iss {
|
namespace iss {
|
||||||
namespace {
|
namespace interp {
|
||||||
volatile std::array<bool, 2> dummy = {
|
using namespace sysc;
|
||||||
core_factory::instance().register_creator("tgc_c|m_p|interp", [](unsigned gdb_port, void* data) -> std::tuple<cpu_ptr, vm_ptr>{
|
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 cc = reinterpret_cast<sysc::tgfs::core_complex*>(data);
|
||||||
arch::tgc_c* lcpu = new sc_core_adapter<arch::riscv_hart_m_p<arch::tgc_c>>(cc);
|
auto* cpu = new sc_core_adapter<arch::riscv_hart_m_p<arch::tgc5c>>(cc);
|
||||||
return {cpu_ptr{lcpu}, vm_ptr{interp::create(lcpu, gdb_port)}};
|
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::tgc5c*>(cpu), gdb_port)}};
|
||||||
}),
|
}),
|
||||||
core_factory::instance().register_creator("tgc_c|mu_p|interp", [](unsigned gdb_port, void* data) -> std::tuple<cpu_ptr, vm_ptr>{
|
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 cc = reinterpret_cast<sysc::tgfs::core_complex*>(data);
|
||||||
arch::tgc_c* lcpu = new sc_core_adapter<arch::riscv_hart_mu_p<arch::tgc_c>>(cc);
|
auto* cpu = new sc_core_adapter<arch::riscv_hart_mu_p<arch::tgc5c>>(cc);
|
||||||
return {cpu_ptr{lcpu}, vm_ptr{interp::create(lcpu, gdb_port)}};
|
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
|
||||||
|
|||||||
@@ -8,17 +8,15 @@
|
|||||||
#ifndef _SYSC_SC_CORE_ADAPTER_H_
|
#ifndef _SYSC_SC_CORE_ADAPTER_H_
|
||||||
#define _SYSC_SC_CORE_ADAPTER_H_
|
#define _SYSC_SC_CORE_ADAPTER_H_
|
||||||
|
|
||||||
|
#include "sc_core_adapter_if.h"
|
||||||
#include <scc/report.h>
|
#include <iostream>
|
||||||
#include <util/ities.h>
|
|
||||||
#include "core_complex.h"
|
|
||||||
#include <iss/iss.h>
|
#include <iss/iss.h>
|
||||||
#include <iss/vm_types.h>
|
#include <iss/vm_types.h>
|
||||||
#include <iostream>
|
#include <scc/report.h>
|
||||||
|
#include <util/ities.h>
|
||||||
|
|
||||||
|
namespace sysc {
|
||||||
template<typename PLAT>
|
template <typename PLAT> class sc_core_adapter : public PLAT, public sc_core_adapter_if {
|
||||||
class sc_core_adapter : public PLAT {
|
|
||||||
public:
|
public:
|
||||||
using reg_t = typename iss::arch::traits<typename PLAT::core>::reg_t;
|
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 phys_addr_t = typename iss::arch::traits<typename PLAT::core>::phys_addr_t;
|
||||||
@@ -26,18 +24,27 @@ public:
|
|||||||
sc_core_adapter(sysc::tgfs::core_complex* owner)
|
sc_core_adapter(sysc::tgfs::core_complex* owner)
|
||||||
: owner(owner) {}
|
: owner(owner) {}
|
||||||
|
|
||||||
uint32_t get_mode() { return this->reg.PRIV; }
|
iss::arch_if* get_arch_if() override { return this; }
|
||||||
|
|
||||||
inline void set_interrupt_execution(bool v) { this->interrupt_sim = v?1:0; }
|
void set_mhartid(unsigned id) override { PLAT::set_mhartid(id); }
|
||||||
|
|
||||||
inline bool get_interrupt_execution() { return this->interrupt_sim; }
|
uint32_t get_mode() override { return this->reg.PRIV; }
|
||||||
|
|
||||||
heart_state_t &get_state() { return this->state; }
|
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 {
|
void notify_phase(iss::arch_if::exec_phase p) override {
|
||||||
if (p == iss::arch_if::ISTART)
|
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());
|
owner->sync(this->instr_if.get_total_cycles());
|
||||||
}
|
}
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
|
||||||
iss::sync_type needed_sync() const override { return iss::PRE_SYNC; }
|
iss::sync_type needed_sync() const override { return iss::PRE_SYNC; }
|
||||||
|
|
||||||
@@ -45,9 +52,8 @@ public:
|
|||||||
static constexpr std::array<const char, 4> lvl = {{'U', 'S', 'H', 'M'}};
|
static constexpr std::array<const char, 4> lvl = {{'U', 'S', 'H', 'M'}};
|
||||||
if(!owner->disass_output(pc, instr)) {
|
if(!owner->disass_output(pc, instr)) {
|
||||||
std::stringstream s;
|
std::stringstream s;
|
||||||
s << "[p:" << lvl[this->reg.PRIV] << ";s:0x" << std::hex << std::setfill('0')
|
s << "[p:" << lvl[this->reg.PRIV] << ";s:0x" << std::hex << std::setfill('0') << std::setw(sizeof(reg_t) * 2)
|
||||||
<< std::setw(sizeof(reg_t) * 2) << (reg_t)this->state.mstatus << std::dec << ";c:"
|
<< (reg_t)this->state.mstatus << std::dec << ";c:" << this->reg.icount + this->cycle_offset << "]";
|
||||||
<< this->reg.icount + this->cycle_offset << "]";
|
|
||||||
SCCDEBUG(owner->name()) << "disass: "
|
SCCDEBUG(owner->name()) << "disass: "
|
||||||
<< "0x" << std::setw(16) << std::right << std::setfill('0') << std::hex << pc << "\t\t" << std::setw(40)
|
<< "0x" << std::setw(16) << std::right << std::setfill('0') << std::hex << pc << "\t\t" << std::setw(40)
|
||||||
<< std::setfill(' ') << std::left << instr << s.str();
|
<< std::setfill(' ') << std::left << instr << s.str();
|
||||||
@@ -66,16 +72,44 @@ public:
|
|||||||
if(addr.access && iss::access_type::DEBUG)
|
if(addr.access && iss::access_type::DEBUG)
|
||||||
return owner->write_mem_dbg(addr.val, length, data) ? iss::Ok : iss::Err;
|
return owner->write_mem_dbg(addr.val, length, data) ? iss::Ok : iss::Err;
|
||||||
else {
|
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;
|
auto res = owner->write_mem(addr.val, length, data) ? iss::Ok : iss::Err;
|
||||||
// clear MTIP on mtimecmp write
|
// clear MTIP on mtimecmp write
|
||||||
if(addr.val == 0x2004000) {
|
if(addr.val == 0x2004000) {
|
||||||
reg_t val;
|
reg_t val;
|
||||||
this->read_csr(iss::arch::mip, val);
|
this->read_csr(iss::arch::mip, val);
|
||||||
if (val & (1ULL << 7)) this->write_csr(iss::arch::mip, val & ~(1ULL << 7));
|
if(val & (1ULL << 7))
|
||||||
|
this->write_csr(iss::arch::mip, val & ~(1ULL << 7));
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
iss::status read_csr(unsigned addr, reg_t& val) override {
|
iss::status read_csr(unsigned addr, reg_t& val) override {
|
||||||
#ifndef CWR_SYSTEMC
|
#ifndef CWR_SYSTEMC
|
||||||
@@ -85,17 +119,19 @@ public:
|
|||||||
if(addr == iss::arch::time) {
|
if(addr == iss::arch::time) {
|
||||||
val = static_cast<reg_t>(time_val);
|
val = static_cast<reg_t>(time_val);
|
||||||
} else if(addr == iss::arch::timeh) {
|
} else if(addr == iss::arch::timeh) {
|
||||||
if (sizeof(reg_t) != 4) return iss::Err;
|
if(sizeof(reg_t) != 4)
|
||||||
|
return iss::Err;
|
||||||
val = static_cast<reg_t>(time_val >> 32);
|
val = static_cast<reg_t>(time_val >> 32);
|
||||||
}
|
}
|
||||||
return ret?Ok:Err;
|
return ret ? iss::Ok : iss::Err;
|
||||||
#else
|
#else
|
||||||
if((addr == iss::arch::time || addr == iss::arch::timeh)) {
|
if((addr == iss::arch::time || addr == iss::arch::timeh)) {
|
||||||
uint64_t time_val = owner->mtime_i.read();
|
uint64_t time_val = owner->mtime_i.read();
|
||||||
if(addr == iss::arch::time) {
|
if(addr == iss::arch::time) {
|
||||||
val = static_cast<reg_t>(time_val);
|
val = static_cast<reg_t>(time_val);
|
||||||
} else if(addr == iss::arch::timeh) {
|
} else if(addr == iss::arch::timeh) {
|
||||||
if (sizeof(reg_t) != 4) return iss::Err;
|
if(sizeof(reg_t) != 4)
|
||||||
|
return iss::Err;
|
||||||
val = static_cast<reg_t>(time_val >> 32);
|
val = static_cast<reg_t>(time_val >> 32);
|
||||||
}
|
}
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
@@ -113,7 +149,7 @@ public:
|
|||||||
PLAT::wait_until(flags);
|
PLAT::wait_until(flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
void local_irq(short id, bool value) {
|
void local_irq(short id, bool value) override {
|
||||||
reg_t mask = 0;
|
reg_t mask = 0;
|
||||||
switch(id) {
|
switch(id) {
|
||||||
case 3: // SW
|
case 3: // SW
|
||||||
@@ -126,7 +162,8 @@ public:
|
|||||||
mask = 1 << 11;
|
mask = 1 << 11;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if(id>15) mask = 1 << id;
|
if(id > 15)
|
||||||
|
mask = 1 << id;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(value) {
|
if(value) {
|
||||||
@@ -141,8 +178,10 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
sysc::tgfs::core_complex* const owner;
|
sysc::tgfs::core_complex* const owner;
|
||||||
sc_event wfi_evt;
|
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_ */
|
#endif /* _SYSC_SC_CORE_ADAPTER_H_ */
|
||||||
|
|||||||
30
src/sysc/sc_core_adapter_if.h
Normal file
30
src/sysc/sc_core_adapter_if.h
Normal file
@@ -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_ */
|
||||||
530
src/vm/asmjit/helper_func.h
Normal file
530
src/vm/asmjit/helper_func.h
Normal file
@@ -0,0 +1,530 @@
|
|||||||
|
|
||||||
|
|
||||||
|
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) {
|
||||||
|
// 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;");
|
||||||
|
cc.mov(get_reg_ptr(jh, traits::PENDING_TRAP), jh.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;");
|
||||||
|
cc.test(jh.trap_state, jh.trap_state);
|
||||||
|
cc.jnz(jh.trap_entry);
|
||||||
|
|
||||||
|
// Does this need to be done after every single instruction?
|
||||||
|
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);
|
||||||
|
write_reg_to_mem(jh, jh.trap_state, traits::TRAP_STATE);
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
jh.trap_state = load_reg_from_mem(jh, traits::TRAP_STATE);
|
||||||
|
}
|
||||||
|
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//enter_trap(core_ptr, *trap_state, *pc, 0);");
|
||||||
|
|
||||||
|
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);
|
||||||
|
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);
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
// TODO implement
|
||||||
|
|
||||||
|
void gen_raise(jit_holder& jh, uint16_t trap_id, uint16_t cause) { jh.cc.comment("//gen_raise"); }
|
||||||
|
void gen_wait(jit_holder& jh, unsigned type) { jh.cc.comment("//gen_wait"); }
|
||||||
|
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>
|
||||||
|
inline typename std::enable_if_t<std::is_unsigned<T>::value, x86::Gp> gen_ext(jit_holder& jh, T val, unsigned size, bool
|
||||||
|
is_signed) const { auto val_reg = get_reg_for(jh, sizeof(val)*8); auto tmp = get_reg_for(jh, size); jh.cc.mov(val_reg,
|
||||||
|
val); if(is_signed) jh.cc.movsx(tmp, val_reg); else jh.cc.movzx(tmp,val_reg); return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline typename std::enable_if_t<std::is_signed<T>::value, x86::Gp> gen_ext(jit_holder& jh, T val, unsigned size, bool
|
||||||
|
is_signed) const { auto val_reg = get_reg_for(jh, sizeof(val)*8); auto tmp = get_reg_for(jh, size); jh.cc.mov(val_reg,
|
||||||
|
val); if(is_signed) jh.cc.movsx(tmp, val_reg); else jh.cc.movzx(tmp,val_reg); return tmp;
|
||||||
|
} */
|
||||||
|
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);
|
||||||
|
jh.cc.mov(val_reg, val);
|
||||||
|
return gen_ext(jh, val_reg, size, is_signed);
|
||||||
|
}
|
||||||
|
// explicit Gp size cast
|
||||||
|
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.mov(val_reg, x86::ptr_64(val_ptr));
|
||||||
|
cc.and_(val_reg, mask);
|
||||||
|
cc.cmp(ret_reg, 0);
|
||||||
|
cc.jne(jh.trap_entry);
|
||||||
|
return val_reg;
|
||||||
|
}
|
||||||
|
inline x86::Gp gen_read_mem(jit_holder& jh, mem_type_e type, x86::Gp addr, x86::Gp length) {
|
||||||
|
uint32_t length_val = 0;
|
||||||
|
auto length_ptr = jh.cc.newIntPtr();
|
||||||
|
jh.cc.mov(length_ptr, &length_val);
|
||||||
|
jh.cc.mov(x86::ptr_32(length_ptr), length);
|
||||||
|
|
||||||
|
return gen_read_mem(jh, type, addr, length);
|
||||||
|
}
|
||||||
|
inline x86::Gp gen_read_mem(jit_holder& jh, mem_type_e type, uint64_t addr, x86::Gp length) {
|
||||||
|
auto addr_reg = jh.cc.newInt64();
|
||||||
|
jh.cc.mov(addr_reg, addr);
|
||||||
|
|
||||||
|
uint32_t length_val = 0;
|
||||||
|
auto length_ptr = jh.cc.newIntPtr();
|
||||||
|
jh.cc.mov(length_ptr, &length_val);
|
||||||
|
jh.cc.mov(x86::ptr_32(length_ptr), length);
|
||||||
|
|
||||||
|
return gen_read_mem(jh, type, addr_reg, length_val);
|
||||||
|
}
|
||||||
|
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) {
|
||||||
|
auto val_reg = jh.cc.newInt64();
|
||||||
|
jh.cc.mov(val_reg, val);
|
||||||
|
gen_write_mem(jh, type, addr, val_reg);
|
||||||
|
}
|
||||||
|
inline void gen_write_mem(jit_holder& jh, mem_type_e type, x86::Gp addr, x86::Gp val) {
|
||||||
|
x86::Compiler& cc = jh.cc;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
if(val.isGpb()) {
|
||||||
|
cc.invoke(&invokeNode, &write_mem1, FuncSignatureT<uint32_t, uint64_t, uint32_t, uint32_t, uint64_t, uint8_t>());
|
||||||
|
} else if(val.isGpw()) {
|
||||||
|
cc.invoke(&invokeNode, &write_mem2, FuncSignatureT<uint32_t, uint64_t, uint32_t, uint32_t, uint64_t, uint16_t>());
|
||||||
|
} else if(val.isGpd()) {
|
||||||
|
cc.invoke(&invokeNode, &write_mem4, FuncSignatureT<uint32_t, uint64_t, uint32_t, uint32_t, uint64_t, uint32_t>());
|
||||||
|
} else if(val.isGpq()) {
|
||||||
|
cc.invoke(&invokeNode, &write_mem8, FuncSignatureT<uint32_t, uint64_t, uint32_t, uint32_t, uint64_t, uint64_t>());
|
||||||
|
} else
|
||||||
|
throw std::runtime_error("Invalid register size in gen_write_mem");
|
||||||
|
|
||||||
|
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) {
|
||||||
|
auto addr_reg = jh.cc.newInt64();
|
||||||
|
jh.cc.mov(addr_reg, addr);
|
||||||
|
gen_write_mem(jh, type, addr_reg, val);
|
||||||
|
}
|
||||||
|
inline void gen_write_mem(jit_holder& jh, mem_type_e type, uint64_t addr, int64_t val) {
|
||||||
|
auto val_reg = jh.cc.newInt64();
|
||||||
|
jh.cc.mov(val_reg, val);
|
||||||
|
|
||||||
|
auto addr_reg = jh.cc.newInt64();
|
||||||
|
jh.cc.mov(addr_reg, addr);
|
||||||
|
gen_write_mem(jh, type, addr_reg, val_reg);
|
||||||
|
}
|
||||||
3555
src/vm/asmjit/vm_tgc5c.cpp
Normal file
3555
src/vm/asmjit/vm_tgc5c.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@@ -35,32 +35,24 @@
|
|||||||
#include "fp_functions.h"
|
#include "fp_functions.h"
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include <softfloat.h>
|
|
||||||
#include "internals.h"
|
#include "internals.h"
|
||||||
#include "specialize.h"
|
#include "specialize.h"
|
||||||
|
#include <softfloat.h>
|
||||||
}
|
}
|
||||||
|
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
|
||||||
using this_t = uint8_t*;
|
using this_t = uint8_t*;
|
||||||
const uint8_t rmm_map[] = {
|
const uint8_t rmm_map[] = {
|
||||||
softfloat_round_near_even /*RNE*/,
|
softfloat_round_near_even /*RNE*/, softfloat_round_minMag /*RTZ*/, softfloat_round_min /*RDN*/, softfloat_round_max /*RUP?*/,
|
||||||
softfloat_round_minMag/*RTZ*/,
|
softfloat_round_near_maxMag /*RMM*/, softfloat_round_max /*RTZ*/, softfloat_round_max /*RTZ*/, softfloat_round_max /*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;
|
const uint32_t quiet_nan32 = 0x7fC00000;
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
||||||
uint32_t fget_flags(){
|
uint32_t fget_flags() { return softfloat_exceptionFlags & 0x1f; }
|
||||||
return softfloat_exceptionFlags&0x1f;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t fadd_s(uint32_t v1, uint32_t v2, uint8_t mode) {
|
uint32_t fadd_s(uint32_t v1, uint32_t v2, uint8_t mode) {
|
||||||
float32_t v1f{v1}, v2f{v2};
|
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) {
|
switch(op) {
|
||||||
case 0:
|
case 0:
|
||||||
if(nan | snan) {
|
if(nan | snan) {
|
||||||
if(snan) softfloat_raiseFlags(softfloat_flag_invalid);
|
if(snan)
|
||||||
|
softfloat_raiseFlags(softfloat_flag_invalid);
|
||||||
return 0;
|
return 0;
|
||||||
} else
|
} else
|
||||||
return f32_eq(v1f, v2f) ? 1 : 0;
|
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_roundingMode = rmm_map[mode & 0x7];
|
||||||
softfloat_exceptionFlags = 0;
|
softfloat_exceptionFlags = 0;
|
||||||
float32_t res = softfloat_mulAddF32(v1, v2, v3, op & 0x1);
|
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;
|
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 v2_nan = (v2 & defaultNaNF32UI) == defaultNaNF32UI;
|
||||||
bool v1_snan = softfloat_isSigNaNF32UI(v1);
|
bool v1_snan = softfloat_isSigNaNF32UI(v1);
|
||||||
bool v2_snan = softfloat_isSigNaNF32UI(v2);
|
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)
|
if(v1_nan || v1_snan)
|
||||||
return (v2_nan || v2_snan) ? defaultNaNF32UI : v2;
|
return (v2_nan || v2_snan) ? defaultNaNF32UI : v2;
|
||||||
else
|
else if(v2_nan || v2_snan)
|
||||||
if (v2_nan || v2_snan)
|
|
||||||
return v1;
|
return v1;
|
||||||
else {
|
else {
|
||||||
if((v1 & 0x7fffffff) == 0 && (v2 & 0x7fffffff) == 0) {
|
if((v1 & 0x7fffffff) == 0 && (v2 & 0x7fffffff) == 0) {
|
||||||
@@ -202,17 +196,10 @@ uint32_t fclass_s( uint32_t v1 ){
|
|||||||
bool isNaN = isNaNF32UI(uiA);
|
bool isNaN = isNaNF32UI(uiA);
|
||||||
bool isSNaN = softfloat_isSigNaNF32UI(uiA);
|
bool isSNaN = softfloat_isSigNaNF32UI(uiA);
|
||||||
|
|
||||||
return
|
return (sign && infOrNaN && fracZero) << 0 | (sign && !infOrNaN && !subnormalOrZero) << 1 |
|
||||||
( sign && infOrNaN && fracZero ) << 0 |
|
(sign && subnormalOrZero && !fracZero) << 2 | (sign && subnormalOrZero && fracZero) << 3 | (!sign && infOrNaN && fracZero) << 7 |
|
||||||
( sign && !infOrNaN && !subnormalOrZero ) << 1 |
|
(!sign && !infOrNaN && !subnormalOrZero) << 6 | (!sign && subnormalOrZero && !fracZero) << 5 |
|
||||||
( sign && subnormalOrZero && !fracZero ) << 2 |
|
(!sign && subnormalOrZero && fracZero) << 4 | (isNaN && isSNaN) << 8 | (isNaN && !isSNaN) << 9;
|
||||||
( 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) {
|
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) {
|
switch(op) {
|
||||||
case 0:
|
case 0:
|
||||||
if(nan | snan) {
|
if(nan | snan) {
|
||||||
if(snan) softfloat_raiseFlags(softfloat_flag_invalid);
|
if(snan)
|
||||||
|
softfloat_raiseFlags(softfloat_flag_invalid);
|
||||||
return 0;
|
return 0;
|
||||||
} else
|
} else
|
||||||
return f64_eq(v1f, v2f) ? 1 : 0;
|
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_roundingMode = rmm_map[mode & 0x7];
|
||||||
softfloat_exceptionFlags = 0;
|
softfloat_exceptionFlags = 0;
|
||||||
float64_t res = softfloat_mulAddF64(v1, v2, v3, op & 0x1);
|
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;
|
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 v2_nan = (v2 & defaultNaNF64UI) == defaultNaNF64UI;
|
||||||
bool v1_snan = softfloat_isSigNaNF64UI(v1);
|
bool v1_snan = softfloat_isSigNaNF64UI(v1);
|
||||||
bool v2_snan = softfloat_isSigNaNF64UI(v2);
|
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)
|
if(v1_nan || v1_snan)
|
||||||
return (v2_nan || v2_snan) ? defaultNaNF64UI : v2;
|
return (v2_nan || v2_snan) ? defaultNaNF64UI : v2;
|
||||||
else
|
else if(v2_nan || v2_snan)
|
||||||
if (v2_nan || v2_snan)
|
|
||||||
return v1;
|
return v1;
|
||||||
else {
|
else {
|
||||||
if((v1 & std::numeric_limits<int64_t>::max()) == 0 && (v2 & std::numeric_limits<int64_t>::max()) == 0) {
|
if((v1 & std::numeric_limits<int64_t>::max()) == 0 && (v2 & std::numeric_limits<int64_t>::max()) == 0) {
|
||||||
return op == 0 ?
|
return op == 0 ? ((v1 & std::numeric_limits<int64_t>::min()) ? v1 : v2)
|
||||||
((v1 & std::numeric_limits<int64_t>::min()) ? v1 : v2) :
|
: ((v1 & std::numeric_limits<int64_t>::min()) ? v2 : v1);
|
||||||
((v1 & std::numeric_limits<int64_t>::min()) ? v2 : v1);
|
|
||||||
} else {
|
} else {
|
||||||
float64_t v1f{v1}, v2f{v2};
|
float64_t v1f{v1}, v2f{v2};
|
||||||
return op == 0 ?
|
return op == 0 ? (f64_lt(v1f, v2f) ? v1 : v2) : (f64_lt(v1f, v2f) ? v2 : v1);
|
||||||
(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 isNaN = isNaNF64UI(uiA);
|
||||||
bool isSNaN = softfloat_isSigNaNF64UI(uiA);
|
bool isSNaN = softfloat_isSigNaNF64UI(uiA);
|
||||||
|
|
||||||
return
|
return (sign && infOrNaN && fracZero) << 0 | (sign && !infOrNaN && !subnormalOrZero) << 1 |
|
||||||
( sign && infOrNaN && fracZero ) << 0 |
|
(sign && subnormalOrZero && !fracZero) << 2 | (sign && subnormalOrZero && fracZero) << 3 | (!sign && infOrNaN && fracZero) << 7 |
|
||||||
( sign && !infOrNaN && !subnormalOrZero ) << 1 |
|
(!sign && !infOrNaN && !subnormalOrZero) << 6 | (!sign && subnormalOrZero && !fracZero) << 5 |
|
||||||
( sign && subnormalOrZero && !fracZero ) << 2 |
|
(!sign && subnormalOrZero && fracZero) << 4 | (isNaN && isSNaN) << 8 | (isNaN && !isSNaN) << 9;
|
||||||
( 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) {
|
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();
|
return v & std::numeric_limits<uint32_t>::max();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
2713
src/vm/interp/vm_tgc5c.cpp
Normal file
2713
src/vm/interp/vm_tgc5c.cpp
Normal file
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>
|
#include <iss/llvm/vm_base.h>
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include <softfloat.h>
|
|
||||||
#include "internals.h"
|
#include "internals.h"
|
||||||
#include "specialize.h"
|
#include "specialize.h"
|
||||||
|
#include <softfloat.h>
|
||||||
}
|
}
|
||||||
|
|
||||||
#include <limits>
|
#include <limits>
|
||||||
@@ -69,7 +69,6 @@ using namespace ::llvm;
|
|||||||
FunctionType* NAME##_type = FunctionType::get(RET, NAME##_args, false); \
|
FunctionType* NAME##_type = FunctionType::get(RET, NAME##_args, false); \
|
||||||
mod->getOrInsertFunction(#NAME, NAME##_type);
|
mod->getOrInsertFunction(#NAME, NAME##_type);
|
||||||
|
|
||||||
|
|
||||||
void add_fp_functions_2_module(Module* mod, uint32_t flen, uint32_t xlen) {
|
void add_fp_functions_2_module(Module* mod, uint32_t flen, uint32_t xlen) {
|
||||||
if(flen) {
|
if(flen) {
|
||||||
FDECL(fget_flags, INT_TYPE(32));
|
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(fsel_d, INT_TYPE(64), INT_TYPE(64), INT_TYPE(64), INT_TYPE(32));
|
||||||
FDECL(fclass_d, INT_TYPE(64), INT_TYPE(64));
|
FDECL(fclass_d, INT_TYPE(64), INT_TYPE(64));
|
||||||
FDECL(unbox_s, INT_TYPE(32), INT_TYPE(64));
|
FDECL(unbox_s, INT_TYPE(32), INT_TYPE(64));
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
} // namespace fp_impl
|
||||||
}
|
} // namespace llvm
|
||||||
}
|
} // namespace iss
|
||||||
|
|||||||
4107
src/vm/llvm/vm_tgc5c.cpp
Normal file
4107
src/vm/llvm/vm_tgc5c.cpp
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
3370
src/vm/tcc/vm_tgc5c.cpp
Normal file
3370
src/vm/tcc/vm_tgc5c.cpp
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user