Merge branch 'develop' into fix-invalid-pc-on-bubble
This commit is contained in:
62
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
62
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us find and fix the bug
|
||||
title: ''
|
||||
labels: bug
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**Affects version**
|
||||
State which version of gem5 this bug was found in. If on the develop branch state the Commit revision ID you are working.
|
||||
|
||||
**gem5 Modifications**
|
||||
If you have modified gem5 in some way please state, to the best of your ability, how it has been modified.
|
||||
|
||||
**To Reproduce**
|
||||
Steps to reproduce the behavior. Please assume starting from a clean repository:
|
||||
1. Compile gem5 with command ...
|
||||
2. Execute the simulation with...
|
||||
|
||||
If writing code, or a terminal command, use code blocks. Either an inline code block, \`scons build/ALL/gem5.opt\` (enclosed in two \`) or a multi-line codeblock:
|
||||
|
||||
|
||||
\`\`\`
|
||||
|
||||
int x=2;
|
||||
|
||||
int y=3'
|
||||
|
||||
print(x+y);
|
||||
|
||||
\`\`\`
|
||||
|
||||
If possible, please include the Python configuration script used and state clearly any parameters passed.
|
||||
|
||||
**Terminal Output**
|
||||
If applicable, add the terminal output here. If long, only include the relevant lines.
|
||||
Please put the terminal output in code blocks. I.e.:
|
||||
|
||||
\`\`\`
|
||||
|
||||
#Terminal output here#
|
||||
|
||||
\`\`\`
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Host Operating System**
|
||||
Ubuntu 22.04, Mac OS X, etc.
|
||||
|
||||
**Host ISA**
|
||||
ARM, X86, RISC-V, etc.
|
||||
|
||||
**Compiler used**
|
||||
State which compiler was used to compile gem5. Please include the compiler version.
|
||||
|
||||
**Additional information**
|
||||
Add any other information which does not fit in the previous sections but may be of use in fixing this bug.
|
||||
5
.github/workflows/ci-tests.yaml
vendored
5
.github/workflows/ci-tests.yaml
vendored
@@ -102,4 +102,9 @@ jobs:
|
||||
name: ${{ env.MY_STEP_VAR }}
|
||||
path: output.zip
|
||||
retention-days: 7
|
||||
- name: Clean runner
|
||||
run:
|
||||
rm -rf ./* || true
|
||||
rm -rf ./.??* || true
|
||||
rm -rf ~/.cache || true
|
||||
- run: echo "This job's status is ${{ job.status }}."
|
||||
|
||||
2
.github/workflows/compiler-tests.yaml
vendored
2
.github/workflows/compiler-tests.yaml
vendored
@@ -16,7 +16,7 @@ jobs:
|
||||
all-compilers:
|
||||
strategy:
|
||||
matrix:
|
||||
image: [gcc-version-12, gcc-version-11, gcc-version-10, gcc-version-9, gcc-version-8, gcc-version-7, clang-version-14, clang-version-13, clang-version-12, clang-version-11, clang-version-10, clang-version-9, clang-version-8, clang-version-7, clang-version-6.0, ubuntu-18.04_all-dependencies, ubuntu-20.04_all-dependencies, ubuntu-22.04_all-dependencies, ubuntu-22.04_min-dependencies]
|
||||
image: [gcc-version-12, gcc-version-11, gcc-version-10, gcc-version-9, gcc-version-8, clang-version-14, clang-version-13, clang-version-12, clang-version-11, clang-version-10, clang-version-9, clang-version-8, clang-version-7, ubuntu-20.04_all-dependencies, ubuntu-22.04_all-dependencies, ubuntu-22.04_min-dependencies]
|
||||
opts: [.opt, .fast]
|
||||
runs-on: [self-hosted, linux, x64, run]
|
||||
timeout-minutes: 2880 # 48 hours
|
||||
|
||||
139
.github/workflows/daily-tests.yaml
vendored
139
.github/workflows/daily-tests.yaml
vendored
@@ -290,6 +290,11 @@ jobs:
|
||||
name: ${{ env.MY_STEP_VAR }}
|
||||
path: output.zip
|
||||
retention-days: 7
|
||||
- name: Clean runner
|
||||
run:
|
||||
rm -rf ./* || true
|
||||
rm -rf ./.??* || true
|
||||
rm -rf ~/.cache || true
|
||||
- run: echo "This job's status is ${{ job.status }}."
|
||||
|
||||
testlib-long-fs:
|
||||
@@ -330,6 +335,11 @@ jobs:
|
||||
name: ${{ env.MY_STEP_VAR }}
|
||||
path: output.zip
|
||||
retention-days: 7
|
||||
- name: Clean runner
|
||||
run:
|
||||
rm -rf ./* || true
|
||||
rm -rf ./.??* || true
|
||||
rm -rf ~/.cache || true
|
||||
- run: echo "This job's status is ${{ job.status }}."
|
||||
|
||||
testlib-long-gem5_library_example_tests:
|
||||
@@ -370,6 +380,11 @@ jobs:
|
||||
name: ${{ env.MY_STEP_VAR }}
|
||||
path: output.zip
|
||||
retention-days: 7
|
||||
- name: Clean runner
|
||||
run:
|
||||
rm -rf ./* || true
|
||||
rm -rf ./.??* || true
|
||||
rm -rf ~/.cache || true
|
||||
- run: echo "This job's status is ${{ job.status }}."
|
||||
|
||||
testlib-long-gpu:
|
||||
@@ -405,6 +420,11 @@ jobs:
|
||||
name: ${{ env.MY_STEP_VAR }}
|
||||
path: output.zip
|
||||
retention-days: 7
|
||||
- name: Clean runner
|
||||
run:
|
||||
rm -rf ./* || true
|
||||
rm -rf ./.??* || true
|
||||
rm -rf ~/.cache || true
|
||||
- run: echo "This job's status is ${{ job.status }}."
|
||||
|
||||
testlib-long-insttest_se:
|
||||
@@ -440,36 +460,46 @@ jobs:
|
||||
name: ${{ env.MY_STEP_VAR }}
|
||||
path: output.zip
|
||||
retention-days: 7
|
||||
- name: Clean runner
|
||||
run:
|
||||
rm -rf ./* || true
|
||||
rm -rf ./.??* || true
|
||||
rm -rf ~/.cache || true
|
||||
- run: echo "This job's status is ${{ job.status }}."
|
||||
|
||||
# kvm tests don't work on github actions
|
||||
# testlib-long-kvm-fork-tests:
|
||||
# runs-on: [self-hosted, linux, x64, run]
|
||||
# container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest
|
||||
# needs: build-gem5
|
||||
# timeout-minutes: 1440 # 24 hours
|
||||
# steps:
|
||||
# - uses: actions/checkout@v3
|
||||
# with:
|
||||
# # Scheduled workflows run on the default branch by default. We
|
||||
# # therefore need to explicitly checkout the develop branch.
|
||||
# ref: develop
|
||||
# - uses: actions/download-artifact@v3
|
||||
# with:
|
||||
# name: ${{ env.artifact-name }}
|
||||
# path: build/ALL/gem5.opt
|
||||
# - run: chmod u+x build/ALL/gem5.opt
|
||||
# - name: long kvm-fork-tests
|
||||
# working-directory: ${{ github.workspace }}/tests
|
||||
# run: ./main.py run gem5/kvm-fork-tests --length=long --skip-build -vv -t $(nproc)
|
||||
# - uses: actions/upload-artifact@v3
|
||||
# env:
|
||||
# MY_STEP_VAR: ${{github.job}}_COMMIT.${{github.sha}}_RUN.${{github.run_id}}_ATTEMPT.${{github.run_attempt}}
|
||||
# with:
|
||||
# name: ${{ env.MY_STEP_VAR }}
|
||||
# path: tests/testing-results
|
||||
# retention-days: 7
|
||||
# - run: echo "This job's status is ${{ job.status }}."
|
||||
# testlib-long-kvm-fork-tests:
|
||||
# runs-on: [self-hosted, linux, x64, run]
|
||||
# container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest
|
||||
# needs: build-gem5
|
||||
# timeout-minutes: 1440 # 24 hours
|
||||
# steps:
|
||||
# - uses: actions/checkout@v3
|
||||
# with:
|
||||
# # Scheduled workflows run on the default branch by default. We
|
||||
# # therefore need to explicitly checkout the develop branch.
|
||||
# ref: develop
|
||||
# - uses: actions/download-artifact@v3
|
||||
# with:
|
||||
# name: ${{ env.artifact-name }}
|
||||
# path: build/ALL/gem5.opt
|
||||
# - run: chmod u+x build/ALL/gem5.opt
|
||||
# - name: long kvm-fork-tests
|
||||
# working-directory: ${{ github.workspace }}/tests
|
||||
# run: ./main.py run gem5/kvm-fork-tests --length=long --skip-build -vv -t $(nproc)
|
||||
# - uses: actions/upload-artifact@v3
|
||||
# env:
|
||||
# MY_STEP_VAR: ${{github.job}}_COMMIT.${{github.sha}}_RUN.${{github.run_id}}_ATTEMPT.${{github.run_attempt}}
|
||||
# with:
|
||||
# name: ${{ env.MY_STEP_VAR }}
|
||||
# path: tests/testing-results
|
||||
# retention-days: 7
|
||||
# - name: Clean runner
|
||||
# run:
|
||||
# rm -rf ./* || true
|
||||
# rm -rf ./.??* || true
|
||||
# rm -rf ~/.cache || true
|
||||
# - run: echo "This job's status is ${{ job.status }}."
|
||||
|
||||
# testlib-long-kvm-switch-tests:
|
||||
# runs-on: [self-hosted, linux, x64, run]
|
||||
@@ -477,11 +507,11 @@ jobs:
|
||||
# needs: build-gem5
|
||||
# timeout-minutes: 1440 # 24 hours
|
||||
# steps:
|
||||
# - uses: actions/checkout@v3
|
||||
# with:
|
||||
# # Scheduled workflows run on the default branch by default. We
|
||||
# # therefore need to explicitly checkout the develop branch.
|
||||
# ref: develop
|
||||
# - uses: actions/checkout@v3
|
||||
# with:
|
||||
# # Scheduled workflows run on the default branch by default. We
|
||||
# # therefore need to explicitly checkout the develop branch.
|
||||
# ref: develop
|
||||
# - uses: actions/download-artifact@v3
|
||||
# with:
|
||||
# name: ${{ env.artifact-name }}
|
||||
@@ -497,6 +527,11 @@ jobs:
|
||||
# name: ${{ env.MY_STEP_VAR }}
|
||||
# path: tests/testing-results
|
||||
# retention-days: 7
|
||||
# - name: Clean runner
|
||||
# run:
|
||||
# rm -rf ./* || true
|
||||
# rm -rf ./.??* || true
|
||||
# rm -rf ~/.cache || true
|
||||
# - run: echo "This job's status is ${{ job.status }}."
|
||||
|
||||
testlib-long-learning_gem5:
|
||||
@@ -532,6 +567,11 @@ jobs:
|
||||
name: ${{ env.MY_STEP_VAR }}
|
||||
path: output.zip
|
||||
retention-days: 7
|
||||
- name: Clean runner
|
||||
run:
|
||||
rm -rf ./* || true
|
||||
rm -rf ./.??* || true
|
||||
rm -rf ~/.cache || true
|
||||
- run: echo "This job's status is ${{ job.status }}."
|
||||
|
||||
testlib-long-m5_threads:
|
||||
@@ -567,6 +607,11 @@ jobs:
|
||||
name: ${{ env.MY_STEP_VAR }}
|
||||
path: output.zip
|
||||
retention-days: 7
|
||||
- name: Clean runner
|
||||
run:
|
||||
rm -rf ./* || true
|
||||
rm -rf ./.??* || true
|
||||
rm -rf ~/.cache || true
|
||||
- run: echo "This job's status is ${{ job.status }}."
|
||||
|
||||
testlib-long-memory:
|
||||
@@ -602,6 +647,11 @@ jobs:
|
||||
name: ${{ env.MY_STEP_VAR }}
|
||||
path: output.zip
|
||||
retention-days: 7
|
||||
- name: Clean runner
|
||||
run:
|
||||
rm -rf ./* || true
|
||||
rm -rf ./.??* || true
|
||||
rm -rf ~/.cache || true
|
||||
- run: echo "This job's status is ${{ job.status }}."
|
||||
|
||||
testlib-long-multi_isa:
|
||||
@@ -647,6 +697,11 @@ jobs:
|
||||
name: ${{ env.MY_STEP_VAR }}
|
||||
path: output.zip
|
||||
retention-days: 7
|
||||
- name: Clean runner
|
||||
run:
|
||||
rm -rf ./* || true
|
||||
rm -rf ./.??* || true
|
||||
rm -rf ~/.cache || true
|
||||
- run: echo "This job's status is ${{ job.status }}."
|
||||
|
||||
testlib-long-replacement-policies:
|
||||
@@ -682,6 +737,11 @@ jobs:
|
||||
name: ${{ env.MY_STEP_VAR }}
|
||||
path: output.zip
|
||||
retention-days: 7
|
||||
- name: Clean runner
|
||||
run:
|
||||
rm -rf ./* || true
|
||||
rm -rf ./.??* || true
|
||||
rm -rf ~/.cache || true
|
||||
- run: echo "This job's status is ${{ job.status }}."
|
||||
|
||||
testlib-long-riscv-boot-tests:
|
||||
@@ -717,6 +777,11 @@ jobs:
|
||||
name: ${{ env.MY_STEP_VAR }}
|
||||
path: output.zip
|
||||
retention-days: 7
|
||||
- name: Clean runner
|
||||
run:
|
||||
rm -rf ./* || true
|
||||
rm -rf ./.??* || true
|
||||
rm -rf ~/.cache || true
|
||||
- run: echo "This job's status is ${{ job.status }}."
|
||||
|
||||
testlib-long-stdlib:
|
||||
@@ -762,6 +827,11 @@ jobs:
|
||||
name: ${{ env.MY_STEP_VAR }}
|
||||
path: output.zip
|
||||
retention-days: 7
|
||||
- name: Clean runner
|
||||
run:
|
||||
rm -rf ./* || true
|
||||
rm -rf ./.??* || true
|
||||
rm -rf ~/.cache || true
|
||||
- run: echo "This job's status is ${{ job.status }}."
|
||||
|
||||
testlib-long-x86-boot-tests:
|
||||
@@ -797,6 +867,11 @@ jobs:
|
||||
name: ${{ env.MY_STEP_VAR }}
|
||||
path: output.zip
|
||||
retention-days: 7
|
||||
- name: Clean runner
|
||||
run:
|
||||
rm -rf ./* || true
|
||||
rm -rf ./.??* || true
|
||||
rm -rf ~/.cache || true
|
||||
- run: echo "This job's status is ${{ job.status }}."
|
||||
|
||||
# This runs the SST-gem5 integration compilation and tests it with
|
||||
|
||||
20
.github/workflows/weekly-tests.yaml
vendored
20
.github/workflows/weekly-tests.yaml
vendored
@@ -67,6 +67,11 @@ jobs:
|
||||
name: ${{ env.MY_STEP_VAR }}
|
||||
path: output.zip
|
||||
retention-days: 7
|
||||
- name: Clean runner
|
||||
run:
|
||||
rm -rf ./* || true
|
||||
rm -rf ./.??* || true
|
||||
rm -rf ~/.cache || true
|
||||
- run: echo "This job's status is ${{ job.status }}."
|
||||
|
||||
|
||||
@@ -103,6 +108,11 @@ jobs:
|
||||
name: ${{ env.MY_STEP_VAR }}
|
||||
path: output.zip
|
||||
retention-days: 7
|
||||
- name: Clean runner
|
||||
run:
|
||||
rm -rf ./* || true
|
||||
rm -rf ./.??* || true
|
||||
rm -rf ~/.cache || true
|
||||
- run: echo "This job's status is ${{ job.status }}."
|
||||
|
||||
testlib-very-long-parsec-benchmarks:
|
||||
@@ -138,6 +148,11 @@ jobs:
|
||||
name: ${{ env.MY_STEP_VAR }}
|
||||
path: output.zip
|
||||
retention-days: 7
|
||||
- name: Clean runner
|
||||
run:
|
||||
rm -rf ./* || true
|
||||
rm -rf ./.??* || true
|
||||
rm -rf ~/.cache || true
|
||||
- run: echo "This job's status is ${{ job.status }}."
|
||||
|
||||
testlib-very-long-x86-boot-tests:
|
||||
@@ -173,4 +188,9 @@ jobs:
|
||||
name: ${{ env.MY_STEP_VAR }}
|
||||
path: output.zip
|
||||
retention-days: 7
|
||||
- name: Clean runner
|
||||
run:
|
||||
rm -rf ./* || true
|
||||
rm -rf ./.??* || true
|
||||
rm -rf ~/.cache || true
|
||||
- run: echo "This job's status is ${{ job.status }}."
|
||||
|
||||
43
README
43
README
@@ -1,43 +0,0 @@
|
||||
This is the gem5 simulator.
|
||||
|
||||
The main website can be found at http://www.gem5.org
|
||||
|
||||
A good starting point is http://www.gem5.org/about, and for
|
||||
more information about building the simulator and getting started
|
||||
please see http://www.gem5.org/documentation and
|
||||
http://www.gem5.org/documentation/learning_gem5/introduction.
|
||||
|
||||
To build gem5, you will need the following software: g++ or clang,
|
||||
Python (gem5 links in the Python interpreter), SCons, zlib, m4, and lastly
|
||||
protobuf if you want trace capture and playback support. Please see
|
||||
http://www.gem5.org/documentation/general_docs/building for more details
|
||||
concerning the minimum versions of these tools.
|
||||
|
||||
Once you have all dependencies resolved, type 'scons
|
||||
build/<CONFIG>/gem5.opt' where CONFIG is one of the options in build_opts like
|
||||
ARM, NULL, MIPS, POWER, SPARC, X86, Garnet_standalone, etc. This will build an
|
||||
optimized version of the gem5 binary (gem5.opt) with the the specified
|
||||
configuration. See http://www.gem5.org/documentation/general_docs/building for
|
||||
more details and options.
|
||||
|
||||
The main source tree includes these subdirectories:
|
||||
- build_opts: pre-made default configurations for gem5
|
||||
- build_tools: tools used internally by gem5's build process.
|
||||
- configs: example simulation configuration scripts
|
||||
- ext: less-common external packages needed to build gem5
|
||||
- include: include files for use in other programs
|
||||
- site_scons: modular components of the build system
|
||||
- src: source code of the gem5 simulator
|
||||
- system: source for some optional system software for simulated systems
|
||||
- tests: regression tests
|
||||
- util: useful utility programs and files
|
||||
|
||||
To run full-system simulations, you may need compiled system firmware, kernel
|
||||
binaries and one or more disk images, depending on gem5's configuration and
|
||||
what type of workload you're trying to run. Many of those resources can be
|
||||
downloaded from http://resources.gem5.org, and/or from the git repository here:
|
||||
https://gem5.googlesource.com/public/gem5-resources/
|
||||
|
||||
If you have questions, please send mail to gem5-users@gem5.org
|
||||
|
||||
Enjoy using gem5 and please share your modifications and extensions.
|
||||
90
README.md
Normal file
90
README.md
Normal file
@@ -0,0 +1,90 @@
|
||||
# The gem5 Simulator
|
||||
|
||||
This is the repository for the gem5 simulator. It contains the full source code
|
||||
for the simulator and all tests and regressions.
|
||||
|
||||
The gem5 simulator is a modular platform for computer-system architecture
|
||||
research, encompassing system-level architecture as well as processor
|
||||
microarchitecture. It is primarily used to evaluate new hardware designs,
|
||||
system software changes, and compile-time and run-time system optimizations.
|
||||
|
||||
The main website can be found at <http://www.gem5.org>.
|
||||
|
||||
## Getting started
|
||||
|
||||
A good starting point is <http://www.gem5.org/about>, and for
|
||||
more information about building the simulator and getting started
|
||||
please see <http://www.gem5.org/documentation> and
|
||||
<http://www.gem5.org/documentation/learning_gem5/introduction>.
|
||||
|
||||
## Building gem5
|
||||
|
||||
To build gem5, you will need the following software: g++ or clang,
|
||||
Python (gem5 links in the Python interpreter), SCons, zlib, m4, and lastly
|
||||
protobuf if you want trace capture and playback support. Please see
|
||||
<http://www.gem5.org/documentation/general_docs/building> for more details
|
||||
concerning the minimum versions of these tools.
|
||||
|
||||
Once you have all dependencies resolved, execute
|
||||
`scons build/ALL/gem5.opt` to build an optimized version of the gem5 binary
|
||||
(`gem5.opt`) containing all gem5 ISAs. If you only wish to compile gem5 to
|
||||
include a single ISA, you can replace `ALL` with the name of the ISA. Valid
|
||||
options include `ARM`, `NULL`, `MIPS`, `POWER`, `SPARC`, and `X86` The complete
|
||||
list of options can be found in the build_opts directory.
|
||||
|
||||
See https://www.gem5.org/documentation/general_docs/building for more
|
||||
information on building gem5.
|
||||
|
||||
## The Source Tree
|
||||
|
||||
The main source tree includes these subdirectories:
|
||||
|
||||
* build_opts: pre-made default configurations for gem5
|
||||
* build_tools: tools used internally by gem5's build process.
|
||||
* configs: example simulation configuration scripts
|
||||
* ext: less-common external packages needed to build gem5
|
||||
* include: include files for use in other programs
|
||||
* site_scons: modular components of the build system
|
||||
* src: source code of the gem5 simulator. The C++ source, Python wrappers, and Python standard library are found in this directory.
|
||||
* system: source for some optional system software for simulated systems
|
||||
* tests: regression tests
|
||||
* util: useful utility programs and files
|
||||
|
||||
## gem5 Resources
|
||||
|
||||
To run full-system simulations, you may need compiled system firmware, kernel
|
||||
binaries and one or more disk images, depending on gem5's configuration and
|
||||
what type of workload you're trying to run. Many of these resources can be
|
||||
obtained from <https://resources.gem5.org>.
|
||||
|
||||
More information on gem5 Resources can be found at
|
||||
<https://www.gem5.org/documentation/general_docs/gem5_resources/>.
|
||||
|
||||
## Getting Help, Reporting bugs, and Requesting Features
|
||||
|
||||
We provide a variety of channels for users and developers to get help, report
|
||||
bugs, requests features, or engage in community discussions. Below
|
||||
are a few of the most common we recommend using.
|
||||
|
||||
* **GitHub Discussions**: A GitHub Discussions page. This can be used to start
|
||||
discussions or ask questions. Available at
|
||||
<https://github.com/orgs/gem5/discussions>.
|
||||
* **GitHub Issues**: A GitHub Issues page for reporting bugs or requesting
|
||||
features. Available at <https://github.com/gem5/gem5/issues>.
|
||||
* **Jira Issue Tracker**: A Jira Issue Tracker for reporting bugs or requesting
|
||||
features. Available at <https://gem5.atlassian.net/>.
|
||||
* **Slack**: A Slack server with a variety of channels for the gem5 community
|
||||
to engage in a variety of discussions. Please visit
|
||||
<https://www.gem5.org/join-slack> to join.
|
||||
* **gem5-users@gem5.org**: A mailing list for users of gem5 to ask questions
|
||||
or start discussions. To join the mailing list please visit
|
||||
<https://www.gem5.org/mailing_lists>.
|
||||
* **gem5-dev@gem5.org**: A mailing list for developers of gem5 to ask questions
|
||||
or start discussions. To join the mailing list please visit
|
||||
<https://www.gem5.org/mailing_lists>.
|
||||
|
||||
## Contributing to gem5
|
||||
|
||||
We hope you enjoy using gem5. When appropriate we advise charing your
|
||||
contributions to the project. <https://www.gem5.org/contributing> can help you
|
||||
get started. Additional information can be found in the CONTRIBUTING.md file.
|
||||
@@ -51,7 +51,11 @@ args = parser.parse_args()
|
||||
code = code_formatter()
|
||||
|
||||
for source in args.files:
|
||||
src = os.path.basename(source)
|
||||
# We replace the "."s in the file name with underscores to make
|
||||
# it a valid python identifier. With the dot, "README.md" would generate
|
||||
# `README.md = "..."` which is not valid as `md` is not a property of
|
||||
# `README`.
|
||||
src = os.path.basename(source).replace(".", "_")
|
||||
with open(source, "r") as f:
|
||||
data = "".join(f)
|
||||
code("${src} = ${{repr(data)}}")
|
||||
|
||||
@@ -43,7 +43,7 @@ scons build/ARM/gem5.opt
|
||||
|
||||
from gem5.isas import ISA
|
||||
from gem5.utils.requires import requires
|
||||
from gem5.resources.resource import Resource
|
||||
from gem5.resources.resource import obtain_resource
|
||||
from gem5.components.memory import SingleChannelDDR3_1600
|
||||
from gem5.components.processors.cpu_types import CPUTypes
|
||||
from gem5.components.boards.simple_board import SimpleBoard
|
||||
@@ -84,7 +84,7 @@ board.set_se_binary_workload(
|
||||
# Any resource specified in this file will be automatically retrieved.
|
||||
# At the time of writing, this file is a WIP and does not contain all
|
||||
# resources. Jira ticket: https://gem5.atlassian.net/browse/GEM5-1096
|
||||
Resource("arm-hello64-static")
|
||||
obtain_resource("arm-hello64-static")
|
||||
)
|
||||
|
||||
# Lastly we run the simulation.
|
||||
|
||||
@@ -48,7 +48,7 @@ scons build/RISCV/gem5.opt
|
||||
|
||||
from gem5.isas import ISA
|
||||
from gem5.utils.requires import requires
|
||||
from gem5.resources.resource import Resource
|
||||
from gem5.resources.resource import obtain_resource
|
||||
from gem5.components.memory import SingleChannelDDR3_1600
|
||||
from gem5.components.processors.cpu_types import CPUTypes
|
||||
from gem5.components.boards.simple_board import SimpleBoard
|
||||
@@ -89,8 +89,8 @@ board = SimpleBoard(
|
||||
# configs/example/gem5_library/checkpoints/riscv-hello-save-checkpoint.py
|
||||
board.set_se_binary_workload(
|
||||
# the workload should be the same as the save-checkpoint script
|
||||
Resource("riscv-hello"),
|
||||
checkpoint=Resource("riscv-hello-example-checkpoint-v23"),
|
||||
obtain_resource("riscv-hello"),
|
||||
checkpoint=obtain_resource("riscv-hello-example-checkpoint-v23"),
|
||||
)
|
||||
|
||||
simulator = Simulator(
|
||||
|
||||
@@ -46,7 +46,7 @@ scons build/RISCV/gem5.opt
|
||||
import argparse
|
||||
from gem5.isas import ISA
|
||||
from gem5.utils.requires import requires
|
||||
from gem5.resources.resource import Resource
|
||||
from gem5.resources.resource import obtain_resource
|
||||
from gem5.components.memory import SingleChannelDDR3_1600
|
||||
from gem5.components.processors.cpu_types import CPUTypes
|
||||
from gem5.components.boards.simple_board import SimpleBoard
|
||||
@@ -101,7 +101,7 @@ board.set_se_binary_workload(
|
||||
# Any resource specified in this file will be automatically retrieved.
|
||||
# At the time of writing, this file is a WIP and does not contain all
|
||||
# resources. Jira ticket: https://gem5.atlassian.net/browse/GEM5-1096
|
||||
Resource("riscv-hello")
|
||||
obtain_resource("riscv-hello")
|
||||
)
|
||||
|
||||
# Lastly we run the simulation.
|
||||
|
||||
@@ -35,7 +35,7 @@ correctly. If this is not done correctly this script will run with error.
|
||||
|
||||
from gem5.isas import ISA
|
||||
from gem5.utils.requires import requires
|
||||
from gem5.resources.resource import Resource
|
||||
from gem5.resources.resource import obtain_resource
|
||||
from gem5.components.memory import DRAMSysDDR3_1600
|
||||
from gem5.components.processors.cpu_types import CPUTypes
|
||||
from gem5.components.boards.simple_board import SimpleBoard
|
||||
@@ -78,7 +78,7 @@ board.set_se_binary_workload(
|
||||
# Any resource specified in this file will be automatically retrieved.
|
||||
# At the time of writing, this file is a WIP and does not contain all
|
||||
# resources. Jira ticket: https://gem5.atlassian.net/browse/GEM5-1096
|
||||
Resource("arm-hello64-static")
|
||||
obtain_resource("arm-hello64-static")
|
||||
)
|
||||
|
||||
# Lastly we run the simulation.
|
||||
|
||||
@@ -43,7 +43,7 @@ scons build/POWER/gem5.opt
|
||||
|
||||
from gem5.isas import ISA
|
||||
from gem5.utils.requires import requires
|
||||
from gem5.resources.resource import Resource
|
||||
from gem5.resources.resource import obtain_resource
|
||||
from gem5.components.memory import SingleChannelDDR4_2400
|
||||
from gem5.components.processors.cpu_types import CPUTypes
|
||||
from gem5.components.boards.simple_board import SimpleBoard
|
||||
@@ -75,7 +75,7 @@ board = SimpleBoard(
|
||||
cache_hierarchy=cache_hierarchy,
|
||||
)
|
||||
|
||||
board.set_se_binary_workload(Resource("power-hello"))
|
||||
board.set_se_binary_workload(obtain_resource("power-hello"))
|
||||
|
||||
# Lastly we run the simulation.
|
||||
simulator = Simulator(board=board)
|
||||
|
||||
@@ -48,7 +48,7 @@ from gem5.components.cachehierarchies.classic.private_l1_private_l2_cache_hierar
|
||||
from gem5.components.processors.cpu_types import CPUTypes
|
||||
from gem5.isas import ISA
|
||||
from gem5.utils.requires import requires
|
||||
from gem5.resources.resource import Resource
|
||||
from gem5.resources.resource import obtain_resource
|
||||
from gem5.simulate.simulator import Simulator
|
||||
|
||||
# Run a check to ensure the right version of gem5 is being used.
|
||||
@@ -79,8 +79,8 @@ board = RiscvBoard(
|
||||
|
||||
# Set the Full System workload.
|
||||
board.set_kernel_disk_workload(
|
||||
kernel=Resource("riscv-bootloader-vmlinux-5.10"),
|
||||
disk_image=Resource("riscv-disk-img"),
|
||||
kernel=obtain_resource("riscv-bootloader-vmlinux-5.10"),
|
||||
disk_image=obtain_resource("riscv-disk-img"),
|
||||
)
|
||||
|
||||
simulator = Simulator(board=board)
|
||||
|
||||
@@ -37,7 +37,7 @@ scons build/RISCV/gem5.opt
|
||||
```
|
||||
"""
|
||||
|
||||
from gem5.resources.resource import Resource
|
||||
from gem5.resources.resource import obtain_resource
|
||||
from gem5.simulate.simulator import Simulator
|
||||
from gem5.prebuilt.riscvmatched.riscvmatched_board import RISCVMatchedBoard
|
||||
from gem5.isas import ISA
|
||||
@@ -49,7 +49,7 @@ requires(isa_required=ISA.RISCV)
|
||||
board = RISCVMatchedBoard()
|
||||
|
||||
# set the hello world riscv binary as the board workload
|
||||
board.set_se_binary_workload(Resource("riscv-hello"))
|
||||
board.set_se_binary_workload(obtain_resource("riscv-hello"))
|
||||
|
||||
# run the simulation with the RISCV Matched board
|
||||
simulator = Simulator(board=board, full_system=False)
|
||||
|
||||
@@ -63,7 +63,7 @@ from gem5.components.processors.simple_switchable_processor import (
|
||||
from gem5.components.processors.cpu_types import CPUTypes
|
||||
from gem5.isas import ISA
|
||||
from gem5.coherence_protocol import CoherenceProtocol
|
||||
from gem5.resources.resource import Resource
|
||||
from gem5.resources.resource import obtain_resource
|
||||
from gem5.simulate.simulator import Simulator
|
||||
from gem5.simulate.exit_event import ExitEvent
|
||||
|
||||
@@ -203,10 +203,10 @@ board.set_kernel_disk_workload(
|
||||
# The x86 linux kernel will be automatically downloaded to the
|
||||
# `~/.cache/gem5` directory if not already present.
|
||||
# gapbs benchamarks was tested with kernel version 4.19.83
|
||||
kernel=Resource("x86-linux-kernel-4.19.83"),
|
||||
kernel=obtain_resource("x86-linux-kernel-4.19.83"),
|
||||
# The x86-gapbs image will be automatically downloaded to the
|
||||
# `~/.cache/gem5` directory if not already present.
|
||||
disk_image=Resource("x86-gapbs"),
|
||||
disk_image=obtain_resource("x86-gapbs"),
|
||||
readfile_contents=command,
|
||||
)
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@ from gem5.components.processors.simple_switchable_processor import (
|
||||
from gem5.components.processors.cpu_types import CPUTypes
|
||||
from gem5.isas import ISA
|
||||
from gem5.coherence_protocol import CoherenceProtocol
|
||||
from gem5.resources.resource import Resource
|
||||
from gem5.resources.resource import obtain_resource
|
||||
from gem5.simulate.simulator import Simulator
|
||||
from gem5.simulate.simulator import ExitEvent
|
||||
|
||||
@@ -204,10 +204,10 @@ board.set_kernel_disk_workload(
|
||||
# The x86 linux kernel will be automatically downloaded to the
|
||||
# `~/.cache/gem5` directory if not already present.
|
||||
# npb benchamarks was tested with kernel version 4.19.83
|
||||
kernel=Resource("x86-linux-kernel-4.19.83"),
|
||||
kernel=obtain_resource("x86-linux-kernel-4.19.83"),
|
||||
# The x86-npb image will be automatically downloaded to the
|
||||
# `~/.cache/gem5` directory if not already present.
|
||||
disk_image=Resource("x86-npb"),
|
||||
disk_image=obtain_resource("x86-npb"),
|
||||
readfile_contents=command,
|
||||
)
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@ from gem5.components.processors.simple_switchable_processor import (
|
||||
from gem5.components.processors.cpu_types import CPUTypes
|
||||
from gem5.isas import ISA
|
||||
from gem5.coherence_protocol import CoherenceProtocol
|
||||
from gem5.resources.resource import Resource
|
||||
from gem5.resources.resource import obtain_resource
|
||||
from gem5.simulate.simulator import Simulator
|
||||
from gem5.simulate.exit_event import ExitEvent
|
||||
|
||||
@@ -185,10 +185,10 @@ board.set_kernel_disk_workload(
|
||||
# The x86 linux kernel will be automatically downloaded to the
|
||||
# `~/.cache/gem5` directory if not already present.
|
||||
# PARSEC benchamarks were tested with kernel version 4.19.83
|
||||
kernel=Resource("x86-linux-kernel-4.19.83"),
|
||||
kernel=obtain_resource("x86-linux-kernel-4.19.83"),
|
||||
# The x86-parsec image will be automatically downloaded to the
|
||||
# `~/.cache/gem5` directory if not already present.
|
||||
disk_image=Resource("x86-parsec"),
|
||||
disk_image=obtain_resource("x86-parsec"),
|
||||
readfile_contents=command,
|
||||
)
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@ from gem5.components.processors.simple_switchable_processor import (
|
||||
from gem5.components.processors.cpu_types import CPUTypes
|
||||
from gem5.isas import ISA
|
||||
from gem5.coherence_protocol import CoherenceProtocol
|
||||
from gem5.resources.resource import Resource, CustomDiskImageResource
|
||||
from gem5.resources.resource import Resource, DiskImageResource
|
||||
from gem5.simulate.simulator import Simulator
|
||||
from gem5.simulate.exit_event import ExitEvent
|
||||
|
||||
@@ -261,9 +261,7 @@ board.set_kernel_disk_workload(
|
||||
# 5.4.49
|
||||
kernel=Resource("x86-linux-kernel-4.19.83"),
|
||||
# The location of the x86 SPEC CPU 2017 image
|
||||
disk_image=CustomDiskImageResource(
|
||||
args.image, root_partition=args.partition
|
||||
),
|
||||
disk_image=DiskImageResource(args.image, root_partition=args.partition),
|
||||
readfile_contents=command,
|
||||
)
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ from gem5.components.processors.simple_switchable_processor import (
|
||||
from gem5.components.processors.cpu_types import CPUTypes
|
||||
from gem5.isas import ISA
|
||||
from gem5.coherence_protocol import CoherenceProtocol
|
||||
from gem5.resources.resource import Resource, CustomDiskImageResource
|
||||
from gem5.resources.resource import obtain_resource, DiskImageResource
|
||||
from gem5.simulate.simulator import Simulator
|
||||
from gem5.simulate.exit_event import ExitEvent
|
||||
|
||||
@@ -268,18 +268,16 @@ except FileExistsError:
|
||||
|
||||
command = f"{args.benchmark} {args.size} {output_dir}"
|
||||
|
||||
# For enabling CustomResource, we pass an additional parameter to mount the
|
||||
# For enabling DiskImageResource, we pass an additional parameter to mount the
|
||||
# correct partition.
|
||||
|
||||
board.set_kernel_disk_workload(
|
||||
# The x86 linux kernel will be automatically downloaded to the
|
||||
# `~/.cache/gem5` directory if not already present.
|
||||
# SPEC CPU2017 benchamarks were tested with kernel version 4.19.83
|
||||
kernel=Resource("x86-linux-kernel-4.19.83"),
|
||||
kernel=obtain_resource("x86-linux-kernel-4.19.83"),
|
||||
# The location of the x86 SPEC CPU 2017 image
|
||||
disk_image=CustomDiskImageResource(
|
||||
args.image, root_partition=args.partition
|
||||
),
|
||||
disk_image=DiskImageResource(args.image, root_partition=args.partition),
|
||||
readfile_contents=command,
|
||||
)
|
||||
|
||||
|
||||
138
configs/example/gem5_library/x86-ubuntu-run-with-kvm-no-perf.py
Normal file
138
configs/example/gem5_library/x86-ubuntu-run-with-kvm-no-perf.py
Normal file
@@ -0,0 +1,138 @@
|
||||
# Copyright (c) 2023 The Regents of the University of California
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met: redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer;
|
||||
# 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;
|
||||
# neither the name of the copyright holders 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
|
||||
# OWNER 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.
|
||||
|
||||
"""
|
||||
|
||||
This script demonstrates how to use KVM CPU without perf.
|
||||
This simulation boots Ubuntu 18.04 using 2 KVM CPUs without using perf.
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
```
|
||||
scons build/X86/gem5.opt -j`nproc`
|
||||
./build/X86/gem5.opt configs/example/gem5_library/x86-ubuntu-run-with-kvm-no-perf.py
|
||||
```
|
||||
"""
|
||||
|
||||
from gem5.utils.requires import requires
|
||||
from gem5.components.boards.x86_board import X86Board
|
||||
from gem5.components.cachehierarchies.ruby.mesi_two_level_cache_hierarchy import (
|
||||
MESITwoLevelCacheHierarchy,
|
||||
)
|
||||
from gem5.components.memory.single_channel import SingleChannelDDR4_2400
|
||||
from gem5.components.processors.simple_switchable_processor import (
|
||||
SimpleSwitchableProcessor,
|
||||
)
|
||||
from gem5.components.processors.cpu_types import CPUTypes
|
||||
from gem5.isas import ISA
|
||||
from gem5.coherence_protocol import CoherenceProtocol
|
||||
from gem5.simulate.simulator import Simulator
|
||||
from gem5.simulate.exit_event import ExitEvent
|
||||
from gem5.resources.workload import Workload
|
||||
|
||||
# This simulation requires using KVM with gem5 compiled for X86 simulation
|
||||
# and with MESI_Two_Level cache coherence protocol.
|
||||
requires(
|
||||
isa_required=ISA.X86,
|
||||
coherence_protocol_required=CoherenceProtocol.MESI_TWO_LEVEL,
|
||||
kvm_required=True,
|
||||
)
|
||||
|
||||
from gem5.components.cachehierarchies.ruby.mesi_two_level_cache_hierarchy import (
|
||||
MESITwoLevelCacheHierarchy,
|
||||
)
|
||||
|
||||
cache_hierarchy = MESITwoLevelCacheHierarchy(
|
||||
l1d_size="32KiB",
|
||||
l1d_assoc=8,
|
||||
l1i_size="32KiB",
|
||||
l1i_assoc=8,
|
||||
l2_size="512KiB",
|
||||
l2_assoc=16,
|
||||
num_l2_banks=1,
|
||||
)
|
||||
|
||||
# Main memory
|
||||
memory = SingleChannelDDR4_2400(size="3GiB")
|
||||
|
||||
# This is a switchable CPU. We first boot Ubuntu using KVM, then the guest
|
||||
# will exit the simulation by calling "m5 exit" (see the `command` variable
|
||||
# below, which contains the command to be run in the guest after booting).
|
||||
# Upon exiting from the simulation, the Exit Event handler will switch the
|
||||
# CPU type (see the ExitEvent.EXIT line below, which contains a map to
|
||||
# a function to be called when an exit event happens).
|
||||
processor = SimpleSwitchableProcessor(
|
||||
starting_core_type=CPUTypes.KVM,
|
||||
switch_core_type=CPUTypes.TIMING,
|
||||
isa=ISA.X86,
|
||||
num_cores=2,
|
||||
)
|
||||
|
||||
# Here we tell the KVM CPU (the starting CPU) not to use perf.
|
||||
for proc in processor.start:
|
||||
proc.core.usePerf = False
|
||||
|
||||
# Here we setup the board. The X86Board allows for Full-System X86 simulations.
|
||||
board = X86Board(
|
||||
clk_freq="3GHz",
|
||||
processor=processor,
|
||||
memory=memory,
|
||||
cache_hierarchy=cache_hierarchy,
|
||||
)
|
||||
|
||||
# Here we set the Full System workload.
|
||||
# The `set_kernel_disk_workload` function for the X86Board takes a kernel, a
|
||||
# disk image, and, optionally, a command to run.
|
||||
|
||||
# This is the command to run after the system has booted. The first `m5 exit`
|
||||
# will stop the simulation so we can switch the CPU cores from KVM to timing
|
||||
# and continue the simulation to run the echo command, sleep for a second,
|
||||
# then, again, call `m5 exit` to terminate the simulation. After simulation
|
||||
# has ended you may inspect `m5out/system.pc.com_1.device` to see the echo
|
||||
# output.
|
||||
command = (
|
||||
"m5 exit;"
|
||||
+ "echo 'This is running on Timing CPU cores.';"
|
||||
+ "sleep 1;"
|
||||
+ "m5 exit;"
|
||||
)
|
||||
|
||||
workload = Workload("x86-ubuntu-18.04-boot")
|
||||
workload.set_parameter("readfile_contents", command)
|
||||
board.set_workload(workload)
|
||||
|
||||
simulator = Simulator(
|
||||
board=board,
|
||||
on_exit_event={
|
||||
# Here we want override the default behavior for the first m5 exit
|
||||
# exit event. Instead of exiting the simulator, we just want to
|
||||
# switch the processor. The 2nd m5 exit after will revert to using
|
||||
# default behavior where the simulator run will exit.
|
||||
ExitEvent.EXIT: (func() for func in [processor.switch])
|
||||
},
|
||||
)
|
||||
simulator.run()
|
||||
@@ -42,7 +42,7 @@ from gem5.components.processors.simple_processor import SimpleProcessor
|
||||
from gem5.components.processors.cpu_types import CPUTypes
|
||||
from gem5.isas import ISA
|
||||
from gem5.utils.requires import requires
|
||||
from gem5.resources.resource import Resource, CustomResource
|
||||
from gem5.resources.resource import obtain_resource
|
||||
|
||||
import argparse
|
||||
|
||||
@@ -98,8 +98,8 @@ board = LupvBoard(
|
||||
# Set the Full System workload.
|
||||
|
||||
board.set_kernel_disk_workload(
|
||||
kernel=Resource("riscv-lupio-linux-kernel"),
|
||||
disk_image=Resource("riscv-lupio-busybox-img"),
|
||||
kernel=obtain_resource("riscv-lupio-linux-kernel"),
|
||||
disk_image=obtain_resource("riscv-lupio-busybox-img"),
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ from m5.objects import *
|
||||
from os import path
|
||||
|
||||
# For downloading the disk image
|
||||
from gem5.resources.resource import Resource
|
||||
from gem5.resources.resource import obtain_resource
|
||||
|
||||
import argparse
|
||||
|
||||
@@ -139,7 +139,7 @@ cpu_clock_rate = args.cpu_clock_rate
|
||||
memory_size = args.memory_size
|
||||
|
||||
# Try downloading the Resource
|
||||
bbl_resource = Resource("riscv-boot-exit-nodisk")
|
||||
bbl_resource = obtain_resource("riscv-boot-exit-nodisk")
|
||||
bbl_path = bbl_resource.get_local_path()
|
||||
|
||||
system = System()
|
||||
|
||||
@@ -536,6 +536,14 @@ Export('DebugFormatFlag')
|
||||
# the corresponding build directory to pick up generated include
|
||||
# files.
|
||||
env.Append(CPPPATH=Dir('.'))
|
||||
parent_dir_set = set()
|
||||
|
||||
for extra_dir in extras_dir_list:
|
||||
parent_dir_set.add(str(Dir(extra_dir).Dir('..').abspath))
|
||||
|
||||
if not GetOption('duplicate_sources'):
|
||||
for parent_dir in parent_dir_set:
|
||||
env.Append(CPPPATH=Dir(parent_dir))
|
||||
|
||||
for extra_dir in extras_dir_list:
|
||||
env.Append(CPPPATH=Dir(extra_dir))
|
||||
@@ -615,7 +623,7 @@ PySource('m5', 'python/m5/defines.py')
|
||||
|
||||
# Generate a file that wraps the basic top level files
|
||||
gem5py_env.Command('python/m5/info.py',
|
||||
[ File('#/COPYING'), File('#/LICENSE'), File('#/README'),
|
||||
[ File('#/COPYING'), File('#/LICENSE'), File('#/README.md'),
|
||||
"${GEM5PY}", "${INFOPY_PY}" ],
|
||||
MakeAction('"${GEM5PY}" "${INFOPY_PY}" "${TARGET}" '
|
||||
'${SOURCES[:-2]}',
|
||||
|
||||
@@ -53,6 +53,6 @@ class RiscvISA(BaseISA):
|
||||
cxx_header = "arch/riscv/isa.hh"
|
||||
|
||||
check_alignment = Param.Bool(
|
||||
False, "whether to check memory access alignment"
|
||||
True, "whether to check memory access alignment"
|
||||
)
|
||||
riscv_type = Param.RiscvType("RV64", "RV32 or RV64")
|
||||
|
||||
@@ -64,9 +64,10 @@ TEST(AmoTest, AtomicOpMin)
|
||||
std::string test_string_smaller = "apple";
|
||||
std::string test_string_bigger = "cat";
|
||||
|
||||
TypedAtomicOpFunctor<int> *amo_op_int = new AtomicOpMin<int>(10);
|
||||
TypedAtomicOpFunctor<std::string> *amo_op_string =
|
||||
new AtomicOpMin<std::string>("base");
|
||||
std::unique_ptr<TypedAtomicOpFunctor<int>> amo_op_int =
|
||||
std::make_unique<AtomicOpMin<int>>(10);
|
||||
std::unique_ptr<TypedAtomicOpFunctor<std::string>> amo_op_string =
|
||||
std::make_unique<AtomicOpMin<std::string>>("base");
|
||||
amo_op_int->execute(&test_int_smaller);
|
||||
amo_op_int->execute(&test_int_bigger);
|
||||
amo_op_string->execute(&test_string_smaller);
|
||||
@@ -85,9 +86,10 @@ TEST(AmoTest, AtomicOpMax)
|
||||
std::string test_string_smaller = "apple";
|
||||
std::string test_string_bigger = "cat";
|
||||
|
||||
TypedAtomicOpFunctor<int> *amo_op_int = new AtomicOpMax<int>(10);
|
||||
TypedAtomicOpFunctor<std::string> *amo_op_string =
|
||||
new AtomicOpMax<std::string>("base");
|
||||
std::unique_ptr<TypedAtomicOpFunctor<int>> amo_op_int =
|
||||
std::make_unique<AtomicOpMax<int>>(10);
|
||||
std::unique_ptr<TypedAtomicOpFunctor<std::string>> amo_op_string =
|
||||
std::make_unique<AtomicOpMax<std::string>>("base");
|
||||
amo_op_int->execute(&test_int_smaller);
|
||||
amo_op_int->execute(&test_int_bigger);
|
||||
amo_op_string->execute(&test_string_smaller);
|
||||
@@ -104,8 +106,10 @@ TEST(AmoTest, AtomicOpDec)
|
||||
int test_int = 10;
|
||||
char test_char = 'c';
|
||||
|
||||
TypedAtomicOpFunctor<int> *amo_op_int = new AtomicOpDec<int>();
|
||||
TypedAtomicOpFunctor<char> *amo_op_char = new AtomicOpDec<char>();
|
||||
std::unique_ptr<TypedAtomicOpFunctor<int>> amo_op_int =
|
||||
std::make_unique<AtomicOpDec<int>>();
|
||||
std::unique_ptr<TypedAtomicOpFunctor<char>> amo_op_char =
|
||||
std::make_unique<AtomicOpDec<char>>();
|
||||
amo_op_int->execute(&test_int);
|
||||
amo_op_char->execute(&test_char);
|
||||
|
||||
@@ -118,8 +122,10 @@ TEST(AmoTest, AtomicOpInc)
|
||||
int test_int = 10;
|
||||
char test_char = 'c';
|
||||
|
||||
TypedAtomicOpFunctor<int> *amo_op_int = new AtomicOpInc<int>();
|
||||
TypedAtomicOpFunctor<char> *amo_op_char = new AtomicOpInc<char>();
|
||||
std::unique_ptr<TypedAtomicOpFunctor<int>> amo_op_int =
|
||||
std::make_unique<AtomicOpInc<int>>();
|
||||
std::unique_ptr<TypedAtomicOpFunctor<char>> amo_op_char =
|
||||
std::make_unique<AtomicOpInc<char>>();
|
||||
amo_op_int->execute(&test_int);
|
||||
amo_op_char->execute(&test_char);
|
||||
|
||||
@@ -132,8 +138,10 @@ TEST(AmoTest, AtomicOpSub)
|
||||
int test_int = 10;
|
||||
char test_char = 'c';
|
||||
|
||||
TypedAtomicOpFunctor<int> *amo_op_int = new AtomicOpSub<int>(2);
|
||||
TypedAtomicOpFunctor<char> *amo_op_char = new AtomicOpSub<char>('a');
|
||||
std::unique_ptr<TypedAtomicOpFunctor<int>> amo_op_int =
|
||||
std::make_unique<AtomicOpSub<int>>(2);
|
||||
std::unique_ptr<TypedAtomicOpFunctor<char>> amo_op_char =
|
||||
std::make_unique<AtomicOpSub<char>>('a');
|
||||
amo_op_int->execute(&test_int);
|
||||
amo_op_char->execute(&test_char);
|
||||
|
||||
@@ -146,8 +154,10 @@ TEST(AmoTest, AtomicOpAdd)
|
||||
int test_int = 10;
|
||||
char test_char = 'c';
|
||||
|
||||
TypedAtomicOpFunctor<int> *amo_op_int = new AtomicOpAdd<int>(2);
|
||||
TypedAtomicOpFunctor<char> *amo_op_char = new AtomicOpAdd<char>(2);
|
||||
std::unique_ptr<TypedAtomicOpFunctor<int>> amo_op_int =
|
||||
std::make_unique<AtomicOpAdd<int>>(2);
|
||||
std::unique_ptr<TypedAtomicOpFunctor<char>> amo_op_char =
|
||||
std::make_unique<AtomicOpAdd<char>>(2);
|
||||
amo_op_int->execute(&test_int);
|
||||
amo_op_char->execute(&test_char);
|
||||
|
||||
@@ -160,8 +170,10 @@ TEST(AmoTest, AtomicOpExch)
|
||||
int test_int = 10;
|
||||
char test_char = 'c';
|
||||
|
||||
TypedAtomicOpFunctor<int> *amo_op_int = new AtomicOpExch<int>(2);
|
||||
TypedAtomicOpFunctor<char> *amo_op_char = new AtomicOpExch<char>('a');
|
||||
std::unique_ptr<TypedAtomicOpFunctor<int>> amo_op_int =
|
||||
std::make_unique<AtomicOpExch<int>>(2);
|
||||
std::unique_ptr<TypedAtomicOpFunctor<char>> amo_op_char =
|
||||
std::make_unique<AtomicOpExch<char>>('a');
|
||||
amo_op_int->execute(&test_int);
|
||||
amo_op_char->execute(&test_char);
|
||||
|
||||
@@ -174,8 +186,10 @@ TEST(AmoTest, AtomicOpXor)
|
||||
int test_int = 10;
|
||||
char test_char = 'c';
|
||||
|
||||
TypedAtomicOpFunctor<int> *amo_op_int = new AtomicOpXor<int>(2);
|
||||
TypedAtomicOpFunctor<char> *amo_op_char = new AtomicOpXor<char>('a');
|
||||
std::unique_ptr<TypedAtomicOpFunctor<int>> amo_op_int =
|
||||
std::make_unique<AtomicOpXor<int>>(2);
|
||||
std::unique_ptr<TypedAtomicOpFunctor<char>> amo_op_char =
|
||||
std::make_unique<AtomicOpXor<char>>('a');
|
||||
amo_op_int->execute(&test_int);
|
||||
amo_op_char->execute(&test_char);
|
||||
|
||||
@@ -188,8 +202,10 @@ TEST(AmoTest, AtomicOpOr)
|
||||
int test_int = 8;
|
||||
bool test_bool = true;
|
||||
|
||||
TypedAtomicOpFunctor<int> *amo_op_int = new AtomicOpOr<int>(2);
|
||||
TypedAtomicOpFunctor<bool> *amo_op_bool = new AtomicOpOr<bool>(false);
|
||||
std::unique_ptr<TypedAtomicOpFunctor<int>> amo_op_int =
|
||||
std::make_unique<AtomicOpOr<int>>(2);
|
||||
std::unique_ptr<TypedAtomicOpFunctor<bool>> amo_op_bool =
|
||||
std::make_unique<AtomicOpOr<bool>>(false);
|
||||
amo_op_int->execute(&test_int);
|
||||
amo_op_bool->execute(&test_bool);
|
||||
|
||||
@@ -202,8 +218,10 @@ TEST(AmoTest, AtomicOpAnd)
|
||||
int test_int = 10;
|
||||
char test_char = 'c';
|
||||
|
||||
TypedAtomicOpFunctor<int> *amo_op_int = new AtomicOpAnd<int>(6);
|
||||
TypedAtomicOpFunctor<char> *amo_op_char = new AtomicOpAnd<char>('a');
|
||||
std::unique_ptr<TypedAtomicOpFunctor<int>> amo_op_int =
|
||||
std::make_unique<AtomicOpAnd<int>>(6);
|
||||
std::unique_ptr<TypedAtomicOpFunctor<char>> amo_op_char =
|
||||
std::make_unique<AtomicOpAnd<char>>('a');
|
||||
amo_op_int->execute(&test_int);
|
||||
amo_op_char->execute(&test_char);
|
||||
|
||||
@@ -215,8 +233,8 @@ TEST(AmoTest, AtomicGeneric2Op)
|
||||
{
|
||||
int test_int = 9;
|
||||
|
||||
TypedAtomicOpFunctor<int> *amo_op_int =
|
||||
new AtomicGeneric2Op<int>(9, multiply2Op);
|
||||
std::unique_ptr<TypedAtomicOpFunctor<int>> amo_op_int =
|
||||
std::make_unique<AtomicGeneric2Op<int>>(9, multiply2Op);
|
||||
amo_op_int->execute(&test_int);
|
||||
|
||||
EXPECT_EQ(test_int, 81);
|
||||
@@ -226,8 +244,8 @@ TEST(AmoTest, AtomicGeneric3Op)
|
||||
{
|
||||
int test_int = 2;
|
||||
|
||||
TypedAtomicOpFunctor<int> *amo_op_int =
|
||||
new AtomicGeneric3Op<int>(4, 3, multiply3Op);
|
||||
std::unique_ptr<TypedAtomicOpFunctor<int>> amo_op_int =
|
||||
std::make_unique<AtomicGeneric3Op<int>>(4, 3, multiply3Op);
|
||||
amo_op_int->execute(&test_int);
|
||||
|
||||
EXPECT_EQ(test_int, 24);
|
||||
@@ -239,8 +257,8 @@ TEST(AmoTest, AtomicGenericPair3Op)
|
||||
|
||||
std::array<int, 2> a = {6, 3};
|
||||
std::array<int, 2> c = {10, 8};
|
||||
TypedAtomicOpFunctor<int> *amo_op_int =
|
||||
new AtomicGenericPair3Op<int>(a, c, addSubColumns);
|
||||
std::unique_ptr<TypedAtomicOpFunctor<int>> amo_op_int =
|
||||
std::make_unique<AtomicGenericPair3Op<int>>(a, c, addSubColumns);
|
||||
amo_op_int->execute(&test_int);
|
||||
|
||||
EXPECT_EQ(test_int, 10);
|
||||
|
||||
@@ -41,9 +41,12 @@
|
||||
#ifndef __BASE_BITFIELD_HH__
|
||||
#define __BASE_BITFIELD_HH__
|
||||
|
||||
#include <bitset>
|
||||
#include <cassert>
|
||||
#include <climits>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
#include <type_traits>
|
||||
|
||||
namespace gem5
|
||||
@@ -303,40 +306,91 @@ findMsbSet(uint64_t val)
|
||||
return msb;
|
||||
}
|
||||
|
||||
namespace {
|
||||
template<typename T>
|
||||
constexpr bool
|
||||
hasBuiltinCtz() {
|
||||
// Since the defined(__has_builtin) in the subsequent #if statement
|
||||
// won't short-circuit the macro expansion of
|
||||
// __has_builtin(__builtin_ctz), we must explicitly define it as zero
|
||||
// if it's undefined to avoid a preprocessor error.
|
||||
#ifndef __has_builtin
|
||||
# define __has_builtin(foo) 0
|
||||
#endif
|
||||
#if defined(__has_builtin) && __has_builtin(__builtin_ctz)
|
||||
return sizeof(unsigned long long) >= sizeof(T);
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
findLsbSetFallback(uint64_t val) {
|
||||
// Create a mask with val's trailing zeros flipped to 1, lsb set flipped to
|
||||
// 0 and the rest unchanged. This effectively is equivalent to doing -1.
|
||||
// e.g.: 0101000 - 1 = 0100111
|
||||
// ^^^^ ^^^^
|
||||
auto mask = val - 1;
|
||||
// This will create a mask of ones from lsb set to last bit
|
||||
// e.g.: 0101000 ^ 0100111 = 00001111
|
||||
// ^^^^ ^^^^
|
||||
auto masked = val ^ mask;
|
||||
// Shift that mask to that there is 1s only where there was 0s after the
|
||||
// lsb set before
|
||||
// e.g.: 00001111 >> 1 = 00000111 (val is 0101000 in the example)
|
||||
auto ones = masked >> 1;
|
||||
// Number of bit set is the lsb set. This operation should be optimized by
|
||||
// the compiler without unsing intrinsics. This operation will become
|
||||
// constexpr starting from C++23. In the meantime, that fallback should not
|
||||
// be used much in favor of the constexpr intrinsic
|
||||
return std::bitset<sizeof(ones) * CHAR_BIT>(ones).count();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the bit position of the LSB that is set in the input
|
||||
* That function will either use a builting that exploit a "count trailing
|
||||
* zeros" instruction or use a bit-fidling algorithm explained bellow.
|
||||
*
|
||||
* @ingroup api_bitfield
|
||||
*/
|
||||
constexpr int
|
||||
findLsbSet(uint64_t val)
|
||||
findLsbSet(uint64_t val) {
|
||||
if (val == 0) return 64;
|
||||
|
||||
if constexpr (hasBuiltinCtz<decltype(val)>()) {
|
||||
return __builtin_ctzll(val);
|
||||
} else {
|
||||
return findLsbSetFallback(val);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<size_t N>
|
||||
constexpr int
|
||||
findLsbSet(std::bitset<N> bs)
|
||||
{
|
||||
int lsb = 0;
|
||||
if (!val)
|
||||
return sizeof(val) * 8;
|
||||
if (!bits(val, 31, 0)) {
|
||||
lsb += 32;
|
||||
val >>= 32;
|
||||
if constexpr (N <= 64) {
|
||||
return findLsbSet(bs.to_ullong());
|
||||
} else {
|
||||
if (bs.none()) return N;
|
||||
// Mask of ones
|
||||
constexpr std::bitset<N> mask(std::numeric_limits<uint64_t>::max());
|
||||
// Is the lsb set in the rightmost 64 bits ?
|
||||
auto nextQword{bs & mask};
|
||||
int i{0};
|
||||
while (nextQword.none()) {
|
||||
// If no, shift by 64 bits and repeat
|
||||
i += 64;
|
||||
bs >>= 64;
|
||||
nextQword = bs & mask;
|
||||
}
|
||||
// If yes, account for the bumber of 64-bit shifts and add the
|
||||
// remaining using the uint64_t implementation. Store in intermediate
|
||||
// variable to ensure valid conversion from ullong to uint64_t.
|
||||
uint64_t remaining{nextQword.to_ullong()};
|
||||
return i + findLsbSet(remaining);
|
||||
}
|
||||
if (!bits(val, 15, 0)) {
|
||||
lsb += 16;
|
||||
val >>= 16;
|
||||
}
|
||||
if (!bits(val, 7, 0)) {
|
||||
lsb += 8;
|
||||
val >>= 8;
|
||||
}
|
||||
if (!bits(val, 3, 0)) {
|
||||
lsb += 4;
|
||||
val >>= 4;
|
||||
}
|
||||
if (!bits(val, 1, 0)) {
|
||||
lsb += 2;
|
||||
val >>= 2;
|
||||
}
|
||||
if (!bits(val, 0, 0))
|
||||
lsb += 1;
|
||||
return lsb;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -316,6 +316,7 @@ TEST(BitfieldTest, FindLsb)
|
||||
{
|
||||
uint64_t val = (1ULL << 63) + (1 << 1);
|
||||
EXPECT_EQ(1, findLsbSet(val));
|
||||
EXPECT_EQ(1, findLsbSetFallback(val));
|
||||
}
|
||||
|
||||
TEST(BitfieldTest, FindLsbZero)
|
||||
@@ -323,6 +324,23 @@ TEST(BitfieldTest, FindLsbZero)
|
||||
EXPECT_EQ(64, findLsbSet(0));
|
||||
}
|
||||
|
||||
TEST(BitfieldTest, FindLsbGeneralized)
|
||||
{
|
||||
static constexpr size_t N{1000};
|
||||
std::bitset<N> bs{0};
|
||||
EXPECT_EQ(findLsbSet(bs), N);
|
||||
for (size_t i{0}; i < N ; ++i) {
|
||||
bs = std::bitset<N>{1} << i;
|
||||
ASSERT_EQ(findLsbSet(bs), i);
|
||||
}
|
||||
|
||||
const auto leadingOne = std::bitset<N>{1} << (N-1);
|
||||
for (size_t i{0}; i < N ; ++i) {
|
||||
bs = leadingOne | (std::bitset<N>{1} << i);
|
||||
ASSERT_EQ(findLsbSet(bs), i);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The following tests "popCount(X)". popCount counts the number of bits set to
|
||||
* one.
|
||||
|
||||
@@ -42,17 +42,6 @@ namespace gem5
|
||||
IniFile::IniFile()
|
||||
{}
|
||||
|
||||
IniFile::~IniFile()
|
||||
{
|
||||
SectionTable::iterator i = table.begin();
|
||||
SectionTable::iterator end = table.end();
|
||||
|
||||
while (i != end) {
|
||||
delete (*i).second;
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
IniFile::load(const std::string &file)
|
||||
{
|
||||
@@ -82,15 +71,15 @@ IniFile::Section::addEntry(const std::string &entryName,
|
||||
|
||||
if (ei == table.end()) {
|
||||
// new entry
|
||||
table[entryName] = new Entry(value);
|
||||
table.emplace(entryName, value);
|
||||
}
|
||||
else if (append) {
|
||||
// append new reult to old entry
|
||||
ei->second->appendValue(value);
|
||||
ei->second.appendValue(value);
|
||||
}
|
||||
else {
|
||||
// override old entry
|
||||
ei->second->setValue(value);
|
||||
ei->second.setValue(value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,39 +109,42 @@ IniFile::Section::add(const std::string &assignment)
|
||||
|
||||
|
||||
IniFile::Entry *
|
||||
IniFile::Section::findEntry(const std::string &entryName)
|
||||
{
|
||||
return const_cast<IniFile::Entry *>(
|
||||
std::as_const(*this).findEntry(entryName));
|
||||
}
|
||||
|
||||
const IniFile::Entry *
|
||||
IniFile::Section::findEntry(const std::string &entryName) const
|
||||
{
|
||||
referenced = true;
|
||||
|
||||
EntryTable::const_iterator ei = table.find(entryName);
|
||||
auto ei = table.find(entryName);
|
||||
|
||||
return (ei == table.end()) ? NULL : ei->second;
|
||||
return (ei == table.end()) ? nullptr : &ei->second;
|
||||
}
|
||||
|
||||
|
||||
IniFile::Section *
|
||||
IniFile::addSection(const std::string §ionName)
|
||||
{
|
||||
SectionTable::iterator i = table.find(sectionName);
|
||||
|
||||
if (i != table.end()) {
|
||||
return i->second;
|
||||
}
|
||||
else {
|
||||
// new entry
|
||||
Section *sec = new Section();
|
||||
table[sectionName] = sec;
|
||||
return sec;
|
||||
}
|
||||
return &table[sectionName];
|
||||
}
|
||||
|
||||
|
||||
IniFile::Section *
|
||||
IniFile::findSection(const std::string §ionName)
|
||||
{
|
||||
return const_cast<IniFile::Section*>(
|
||||
std::as_const(*this).findSection(sectionName));
|
||||
}
|
||||
|
||||
const IniFile::Section *
|
||||
IniFile::findSection(const std::string §ionName) const
|
||||
{
|
||||
SectionTable::const_iterator i = table.find(sectionName);
|
||||
auto i = table.find(sectionName);
|
||||
|
||||
return (i == table.end()) ? NULL : i->second;
|
||||
return (i == table.end()) ? nullptr : &i->second;
|
||||
}
|
||||
|
||||
|
||||
@@ -215,11 +207,11 @@ bool
|
||||
IniFile::find(const std::string §ionName, const std::string &entryName,
|
||||
std::string &value) const
|
||||
{
|
||||
Section *section = findSection(sectionName);
|
||||
auto* section = findSection(sectionName);
|
||||
if (section == NULL)
|
||||
return false;
|
||||
|
||||
Entry *entry = section->findEntry(entryName);
|
||||
auto* entry = section->findEntry(entryName);
|
||||
if (entry == NULL)
|
||||
return false;
|
||||
|
||||
@@ -232,7 +224,7 @@ bool
|
||||
IniFile::entryExists(const std::string §ionName,
|
||||
const std::string &entryName) const
|
||||
{
|
||||
Section *section = findSection(sectionName);
|
||||
auto* section = findSection(sectionName);
|
||||
|
||||
if (!section)
|
||||
return false;
|
||||
@@ -248,13 +240,13 @@ IniFile::sectionExists(const std::string §ionName) const
|
||||
|
||||
|
||||
bool
|
||||
IniFile::Section::printUnreferenced(const std::string §ionName)
|
||||
IniFile::Section::printUnreferenced(const std::string §ionName) const
|
||||
{
|
||||
bool unref = false;
|
||||
bool search_unref_entries = false;
|
||||
std::vector<std::string> unref_ok_entries;
|
||||
|
||||
Entry *entry = findEntry("unref_entries_ok");
|
||||
auto* entry = findEntry("unref_entries_ok");
|
||||
if (entry != NULL) {
|
||||
tokenize(unref_ok_entries, entry->getValue(), ' ');
|
||||
if (unref_ok_entries.size()) {
|
||||
@@ -262,10 +254,9 @@ IniFile::Section::printUnreferenced(const std::string §ionName)
|
||||
}
|
||||
}
|
||||
|
||||
for (EntryTable::iterator ei = table.begin();
|
||||
ei != table.end(); ++ei) {
|
||||
const std::string &entryName = ei->first;
|
||||
entry = ei->second;
|
||||
for (auto& ei: table) {
|
||||
const std::string &entryName = ei.first;
|
||||
entry = &ei.second;
|
||||
|
||||
if (entryName == "unref_section_ok" ||
|
||||
entryName == "unref_entries_ok")
|
||||
@@ -294,32 +285,29 @@ IniFile::Section::printUnreferenced(const std::string §ionName)
|
||||
void
|
||||
IniFile::getSectionNames(std::vector<std::string> &list) const
|
||||
{
|
||||
for (SectionTable::const_iterator i = table.begin();
|
||||
i != table.end(); ++i)
|
||||
{
|
||||
list.push_back((*i).first);
|
||||
for (auto& entry: table) {
|
||||
auto& sectionName = entry.first;
|
||||
list.push_back(sectionName);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
IniFile::printUnreferenced()
|
||||
IniFile::printUnreferenced() const
|
||||
{
|
||||
bool unref = false;
|
||||
|
||||
for (SectionTable::iterator i = table.begin();
|
||||
i != table.end(); ++i) {
|
||||
const std::string §ionName = i->first;
|
||||
Section *section = i->second;
|
||||
for (auto& entry: table) {
|
||||
auto& [sectionName, section] = entry;
|
||||
|
||||
if (!section->isReferenced()) {
|
||||
if (section->findEntry("unref_section_ok") == NULL) {
|
||||
if (!section.isReferenced()) {
|
||||
if (section.findEntry("unref_section_ok") == NULL) {
|
||||
std::cerr << "Section " << sectionName << " not referenced."
|
||||
<< std::endl;
|
||||
unref = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (section->printUnreferenced(sectionName)) {
|
||||
if (section.printUnreferenced(sectionName)) {
|
||||
unref = true;
|
||||
}
|
||||
}
|
||||
@@ -330,12 +318,11 @@ IniFile::printUnreferenced()
|
||||
|
||||
|
||||
void
|
||||
IniFile::Section::dump(const std::string §ionName)
|
||||
IniFile::Section::dump(const std::string §ionName) const
|
||||
{
|
||||
for (EntryTable::iterator ei = table.begin();
|
||||
ei != table.end(); ++ei) {
|
||||
std::cout << sectionName << ": " << (*ei).first << " => "
|
||||
<< (*ei).second->getValue() << "\n";
|
||||
for (auto& ei: table) {
|
||||
std::cout << sectionName << ": " << ei.first << " => "
|
||||
<< ei.second.getValue() << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -344,7 +331,7 @@ IniFile::dump()
|
||||
{
|
||||
for (SectionTable::iterator i = table.begin();
|
||||
i != table.end(); ++i) {
|
||||
i->second->dump(i->first);
|
||||
i->second.dump(i->first);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -364,9 +351,9 @@ void
|
||||
IniFile::visitSection(const std::string §ionName,
|
||||
IniFile::VisitSectionCallback cb)
|
||||
{
|
||||
const auto& section = *table.at(sectionName);
|
||||
const auto& section = table.at(sectionName);
|
||||
for (const auto& pair : section) {
|
||||
cb(pair.first, pair.second->getValue());
|
||||
cb(pair.first, pair.second.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -72,7 +72,7 @@ class IniFile
|
||||
}
|
||||
|
||||
/// Has this entry been used?
|
||||
bool isReferenced() { return referenced; }
|
||||
bool isReferenced() const { return referenced; }
|
||||
|
||||
/// Fetch the value.
|
||||
const std::string &getValue() const;
|
||||
@@ -94,7 +94,7 @@ class IniFile
|
||||
class Section
|
||||
{
|
||||
/// EntryTable type. Map of strings to Entry object pointers.
|
||||
typedef std::unordered_map<std::string, Entry *> EntryTable;
|
||||
typedef std::unordered_map<std::string, Entry> EntryTable;
|
||||
|
||||
EntryTable table; ///< Table of entries.
|
||||
mutable bool referenced; ///< Has this section been used?
|
||||
@@ -107,7 +107,7 @@ class IniFile
|
||||
}
|
||||
|
||||
/// Has this section been used?
|
||||
bool isReferenced() { return referenced; }
|
||||
bool isReferenced() const { return referenced; }
|
||||
|
||||
/// Add an entry to the table. If an entry with the same name
|
||||
/// already exists, the 'append' parameter is checked If true,
|
||||
@@ -125,24 +125,25 @@ class IniFile
|
||||
|
||||
/// Find the entry with the given name.
|
||||
/// @retval Pointer to the entry object, or NULL if none.
|
||||
Entry *findEntry(const std::string &entryName) const;
|
||||
Entry *findEntry(const std::string &entryName);
|
||||
const Entry *findEntry(const std::string &entryName) const;
|
||||
|
||||
/// Print the unreferenced entries in this section to cerr.
|
||||
/// Messages can be suppressed using "unref_section_ok" and
|
||||
/// "unref_entries_ok".
|
||||
/// @param sectionName Name of this section, for use in output message.
|
||||
/// @retval True if any entries were printed.
|
||||
bool printUnreferenced(const std::string §ionName);
|
||||
bool printUnreferenced(const std::string §ionName) const;
|
||||
|
||||
/// Print the contents of this section to cout (for debugging).
|
||||
void dump(const std::string §ionName);
|
||||
void dump(const std::string §ionName) const;
|
||||
|
||||
EntryTable::const_iterator begin() const;
|
||||
EntryTable::const_iterator end() const;
|
||||
};
|
||||
|
||||
/// SectionTable type. Map of strings to Section object pointers.
|
||||
typedef std::unordered_map<std::string, Section *> SectionTable;
|
||||
typedef std::unordered_map<std::string, Section> SectionTable;
|
||||
|
||||
protected:
|
||||
/// Hash of section names to Section object pointers.
|
||||
@@ -155,15 +156,13 @@ class IniFile
|
||||
|
||||
/// Look up section with the given name.
|
||||
/// @retval Pointer to section object, or NULL if not found.
|
||||
Section *findSection(const std::string §ionName) const;
|
||||
Section *findSection(const std::string §ionName);
|
||||
const Section *findSection(const std::string §ionName) const;
|
||||
|
||||
public:
|
||||
/// Constructor.
|
||||
IniFile();
|
||||
|
||||
/// Destructor.
|
||||
~IniFile();
|
||||
|
||||
/// Load parameter settings from given istream. This is a helper
|
||||
/// function for load(string) and loadCPP(), which open a file
|
||||
/// and then pass it here.
|
||||
@@ -206,7 +205,7 @@ class IniFile
|
||||
|
||||
/// Print unreferenced entries in object. Iteratively calls
|
||||
/// printUnreferend() on all the constituent sections.
|
||||
bool printUnreferenced();
|
||||
bool printUnreferenced() const;
|
||||
|
||||
/// Dump contents to cout. For debugging.
|
||||
void dump();
|
||||
|
||||
@@ -85,7 +85,7 @@ class Memoizer
|
||||
using ret_type = Ret;
|
||||
using args_type = std::tuple<Args...>;
|
||||
|
||||
constexpr Memoizer(Ret _func(Args...))
|
||||
constexpr Memoizer(Ret (*_func)(Args...))
|
||||
: func(_func)
|
||||
{
|
||||
validateMemoizer();
|
||||
|
||||
@@ -70,7 +70,7 @@ class Trie
|
||||
Value *value;
|
||||
|
||||
Node *parent;
|
||||
Node *kids[2];
|
||||
std::unique_ptr<Node> kids[2];
|
||||
|
||||
Node(Key _key, Key _mask, Value *_val) :
|
||||
key(_key & _mask), mask(_mask), value(_val),
|
||||
@@ -83,16 +83,8 @@ class Trie
|
||||
void
|
||||
clear()
|
||||
{
|
||||
if (kids[1]) {
|
||||
kids[1]->clear();
|
||||
delete kids[1];
|
||||
kids[1] = NULL;
|
||||
}
|
||||
if (kids[0]) {
|
||||
kids[0]->clear();
|
||||
delete kids[0];
|
||||
kids[0] = NULL;
|
||||
}
|
||||
kids[1].reset();
|
||||
kids[0].reset();
|
||||
}
|
||||
|
||||
void
|
||||
@@ -188,9 +180,9 @@ class Trie
|
||||
return node;
|
||||
|
||||
if (node->kids[0] && node->kids[0]->matches(key))
|
||||
node = node->kids[0];
|
||||
node = node->kids[0].get();
|
||||
else if (node->kids[1] && node->kids[1]->matches(key))
|
||||
node = node->kids[1];
|
||||
node = node->kids[1].get();
|
||||
else
|
||||
node = NULL;
|
||||
}
|
||||
@@ -225,8 +217,8 @@ class Trie
|
||||
// Walk past all the nodes this new node will be inserted after. They
|
||||
// can be ignored for the purposes of this function.
|
||||
Node *node = &head;
|
||||
while (goesAfter(&node, node->kids[0], key, new_mask) ||
|
||||
goesAfter(&node, node->kids[1], key, new_mask))
|
||||
while (goesAfter(&node, node->kids[0].get(), key, new_mask) ||
|
||||
goesAfter(&node, node->kids[1].get(), key, new_mask))
|
||||
{}
|
||||
assert(node);
|
||||
|
||||
@@ -239,14 +231,13 @@ class Trie
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < 2; i++) {
|
||||
Node *&kid = node->kids[i];
|
||||
Node *new_node;
|
||||
auto& kid = node->kids[i];
|
||||
if (!kid) {
|
||||
// No kid. Add a new one.
|
||||
new_node = new Node(key, new_mask, val);
|
||||
auto new_node = std::make_unique<Node>(key, new_mask, val);
|
||||
new_node->parent = node;
|
||||
kid = new_node;
|
||||
return new_node;
|
||||
kid = std::move(new_node);
|
||||
return kid.get();
|
||||
}
|
||||
|
||||
// Walk down the leg until something doesn't match or we run out
|
||||
@@ -266,23 +257,23 @@ class Trie
|
||||
continue;
|
||||
|
||||
// At the point we walked to above, add a new node.
|
||||
new_node = new Node(key, cur_mask, NULL);
|
||||
auto new_node = std::make_unique<Node>(key, cur_mask, nullptr);
|
||||
new_node->parent = node;
|
||||
kid->parent = new_node;
|
||||
new_node->kids[0] = kid;
|
||||
kid = new_node;
|
||||
kid->parent = new_node.get();
|
||||
new_node->kids[0] = std::move(kid);
|
||||
kid = std::move(new_node);
|
||||
|
||||
// If we ran out of bits, the value goes right here.
|
||||
if (cur_mask == new_mask) {
|
||||
new_node->value = val;
|
||||
return new_node;
|
||||
kid->value = val;
|
||||
return kid.get();
|
||||
}
|
||||
|
||||
// Still more bits to deal with, so add a new node for that path.
|
||||
new_node = new Node(key, new_mask, val);
|
||||
new_node->parent = kid;
|
||||
kid->kids[1] = new_node;
|
||||
return new_node;
|
||||
new_node = std::make_unique<Node>(key, new_mask, val);
|
||||
new_node->parent = kid.get();
|
||||
kid->kids[1] = std::move(new_node);
|
||||
return kid->kids[1].get();
|
||||
}
|
||||
|
||||
panic("Reached the end of the Trie insert function!\n");
|
||||
@@ -332,23 +323,22 @@ class Trie
|
||||
if (node->kids[0])
|
||||
node->kids[0]->parent = parent;
|
||||
// Figure out which kid we are, and update our parent's pointers.
|
||||
if (parent->kids[0] == node)
|
||||
parent->kids[0] = node->kids[0];
|
||||
else if (parent->kids[1] == node)
|
||||
parent->kids[1] = node->kids[0];
|
||||
if (parent->kids[0].get() == node)
|
||||
parent->kids[0] = std::move(node->kids[0]);
|
||||
else if (parent->kids[1].get() == node)
|
||||
parent->kids[1] = std::move(node->kids[0]);
|
||||
else
|
||||
panic("Trie: Inconsistent parent/kid relationship.\n");
|
||||
// Make sure if the parent only has one kid, it's kid[0].
|
||||
if (parent->kids[1] && !parent->kids[0]) {
|
||||
parent->kids[0] = parent->kids[1];
|
||||
parent->kids[1] = NULL;
|
||||
parent->kids[0] = std::move(parent->kids[1]);
|
||||
parent->kids[1] = nullptr;
|
||||
}
|
||||
|
||||
// If the parent has less than two kids and no cargo and isn't the
|
||||
// root, delete it too.
|
||||
if (!parent->kids[1] && !parent->value && parent->parent)
|
||||
remove(parent);
|
||||
delete node;
|
||||
return val;
|
||||
}
|
||||
|
||||
|
||||
@@ -64,6 +64,11 @@ class BaseKvmCPU(BaseCPU):
|
||||
def support_take_over(cls):
|
||||
return True
|
||||
|
||||
usePerf = Param.Bool(
|
||||
True,
|
||||
"Use perf for gathering statistics from the guest and providing "
|
||||
"statistic-related functionalities",
|
||||
)
|
||||
useCoalescedMMIO = Param.Bool(False, "Use coalesced MMIO (EXPERIMENTAL)")
|
||||
usePerfOverflow = Param.Bool(
|
||||
False, "Use perf event overflow counters (EXPERIMENTAL)"
|
||||
|
||||
@@ -71,12 +71,15 @@ BaseKvmCPU::BaseKvmCPU(const BaseKvmCPUParams ¶ms)
|
||||
alwaysSyncTC(params.alwaysSyncTC),
|
||||
threadContextDirty(true),
|
||||
kvmStateDirty(false),
|
||||
usePerf(params.usePerf),
|
||||
vcpuID(-1), vcpuFD(-1), vcpuMMapSize(0),
|
||||
_kvmRun(NULL), mmioRing(NULL),
|
||||
pageSize(sysconf(_SC_PAGE_SIZE)),
|
||||
tickEvent([this]{ tick(); }, "BaseKvmCPU tick",
|
||||
false, Event::CPU_Tick_Pri),
|
||||
activeInstPeriod(0),
|
||||
hwCycles(nullptr),
|
||||
hwInstructions(nullptr),
|
||||
perfControlledByTimer(params.usePerfOverflow),
|
||||
hostFactor(params.hostFactor), stats(this),
|
||||
ctrInsts(0)
|
||||
@@ -96,6 +99,22 @@ BaseKvmCPU::BaseKvmCPU(const BaseKvmCPUParams ¶ms)
|
||||
thread->setStatus(ThreadContext::Halted);
|
||||
tc = thread->getTC();
|
||||
threadContexts.push_back(tc);
|
||||
|
||||
if ((!usePerf) && perfControlledByTimer) {
|
||||
panic("KVM: invalid combination of parameters: cannot use "
|
||||
"perfControlledByTimer without usePerf\n");
|
||||
}
|
||||
|
||||
// If we use perf, we create new PerfKVMCounters
|
||||
if (usePerf) {
|
||||
hwCycles = std::unique_ptr<PerfKvmCounter>(new PerfKvmCounter());
|
||||
hwInstructions = std::unique_ptr<PerfKvmCounter>(new PerfKvmCounter());
|
||||
} else {
|
||||
inform("Using KVM CPU without perf. The stats related to the number "
|
||||
"of cycles and instructions executed by the KVM CPU will not "
|
||||
"be updated. The stats should not be used for performance "
|
||||
"evaluation.");
|
||||
}
|
||||
}
|
||||
|
||||
BaseKvmCPU::~BaseKvmCPU()
|
||||
@@ -248,7 +267,7 @@ BaseKvmCPU::restartEqThread()
|
||||
setupCounters();
|
||||
|
||||
if (p.usePerfOverflow) {
|
||||
runTimer.reset(new PerfKvmTimer(hwCycles,
|
||||
runTimer.reset(new PerfKvmTimer(*hwCycles,
|
||||
KVM_KICK_SIGNAL,
|
||||
p.hostFactor,
|
||||
p.hostFreq));
|
||||
@@ -424,8 +443,10 @@ BaseKvmCPU::notifyFork()
|
||||
vcpuFD = -1;
|
||||
_kvmRun = NULL;
|
||||
|
||||
hwInstructions.detach();
|
||||
hwCycles.detach();
|
||||
if (usePerf) {
|
||||
hwInstructions->detach();
|
||||
hwCycles->detach();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -690,7 +711,9 @@ BaseKvmCPU::kvmRunDrain()
|
||||
uint64_t
|
||||
BaseKvmCPU::getHostCycles() const
|
||||
{
|
||||
return hwCycles.read();
|
||||
if (usePerf)
|
||||
return hwCycles->read();
|
||||
return 0;
|
||||
}
|
||||
|
||||
Tick
|
||||
@@ -746,21 +769,26 @@ BaseKvmCPU::kvmRun(Tick ticks)
|
||||
// Get hardware statistics after synchronizing contexts. The KVM
|
||||
// state update might affect guest cycle counters.
|
||||
uint64_t baseCycles(getHostCycles());
|
||||
uint64_t baseInstrs(hwInstructions.read());
|
||||
uint64_t baseInstrs = 0;
|
||||
if (usePerf) {
|
||||
baseInstrs = hwInstructions->read();
|
||||
}
|
||||
|
||||
// Arm the run timer and start the cycle timer if it isn't
|
||||
// controlled by the overflow timer. Starting/stopping the cycle
|
||||
// timer automatically starts the other perf timers as they are in
|
||||
// the same counter group.
|
||||
runTimer->arm(ticks);
|
||||
if (!perfControlledByTimer)
|
||||
hwCycles.start();
|
||||
if (usePerf && (!perfControlledByTimer)) {
|
||||
hwCycles->start();
|
||||
}
|
||||
|
||||
ioctlRun();
|
||||
|
||||
runTimer->disarm();
|
||||
if (!perfControlledByTimer)
|
||||
hwCycles.stop();
|
||||
if (usePerf && (!perfControlledByTimer)) {
|
||||
hwCycles->stop();
|
||||
}
|
||||
|
||||
// The control signal may have been delivered after we exited
|
||||
// from KVM. It will be pending in that case since it is
|
||||
@@ -771,7 +799,10 @@ BaseKvmCPU::kvmRun(Tick ticks)
|
||||
|
||||
const uint64_t hostCyclesExecuted(getHostCycles() - baseCycles);
|
||||
const uint64_t simCyclesExecuted(hostCyclesExecuted * hostFactor);
|
||||
const uint64_t instsExecuted(hwInstructions.read() - baseInstrs);
|
||||
uint64_t instsExecuted = 0;
|
||||
if (usePerf) {
|
||||
instsExecuted = hwInstructions->read() - baseInstrs;
|
||||
}
|
||||
ticksExecuted = runTimer->ticksFromHostCycles(hostCyclesExecuted);
|
||||
|
||||
/* Update statistics */
|
||||
@@ -1288,13 +1319,14 @@ BaseKvmCPU::setupCounters()
|
||||
|
||||
// We might be re-attaching counters due threads being
|
||||
// re-initialised after fork.
|
||||
if (hwCycles.attached())
|
||||
hwCycles.detach();
|
||||
if (usePerf) {
|
||||
if (hwCycles->attached()) {
|
||||
hwCycles->detach();
|
||||
}
|
||||
|
||||
hwCycles.attach(cfgCycles,
|
||||
0); // TID (0 => currentThread)
|
||||
|
||||
setupInstCounter();
|
||||
hwCycles->attach(cfgCycles, 0); // TID (0 => currentThread)
|
||||
setupInstCounter();
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -1344,10 +1376,16 @@ BaseKvmCPU::setupInstStop()
|
||||
void
|
||||
BaseKvmCPU::setupInstCounter(uint64_t period)
|
||||
{
|
||||
// This function is for setting up instruction counter using perf
|
||||
if (!usePerf) {
|
||||
return;
|
||||
}
|
||||
|
||||
// No need to do anything if we aren't attaching for the first
|
||||
// time or the period isn't changing.
|
||||
if (period == activeInstPeriod && hwInstructions.attached())
|
||||
if (period == activeInstPeriod && hwInstructions->attached()) {
|
||||
return;
|
||||
}
|
||||
|
||||
PerfKvmCounterConfig cfgInstructions(PERF_TYPE_HARDWARE,
|
||||
PERF_COUNT_HW_INSTRUCTIONS);
|
||||
@@ -1366,15 +1404,15 @@ BaseKvmCPU::setupInstCounter(uint64_t period)
|
||||
|
||||
// We need to detach and re-attach the counter to reliably change
|
||||
// sampling settings. See PerfKvmCounter::period() for details.
|
||||
if (hwInstructions.attached())
|
||||
hwInstructions.detach();
|
||||
assert(hwCycles.attached());
|
||||
hwInstructions.attach(cfgInstructions,
|
||||
if (hwInstructions->attached())
|
||||
hwInstructions->detach();
|
||||
assert(hwCycles->attached());
|
||||
hwInstructions->attach(cfgInstructions,
|
||||
0, // TID (0 => currentThread)
|
||||
hwCycles);
|
||||
*hwCycles);
|
||||
|
||||
if (period)
|
||||
hwInstructions.enableSignals(KVM_KICK_SIGNAL);
|
||||
hwInstructions->enableSignals(KVM_KICK_SIGNAL);
|
||||
|
||||
activeInstPeriod = period;
|
||||
}
|
||||
|
||||
@@ -653,6 +653,9 @@ class BaseKvmCPU : public BaseCPU
|
||||
*/
|
||||
bool kvmStateDirty;
|
||||
|
||||
/** True if using perf; False otherwise*/
|
||||
bool usePerf;
|
||||
|
||||
/** KVM internal ID of the vCPU */
|
||||
long vcpuID;
|
||||
|
||||
@@ -763,7 +766,7 @@ class BaseKvmCPU : public BaseCPU
|
||||
* PerfKvmTimer (see perfControlledByTimer) to trigger exits from
|
||||
* KVM.
|
||||
*/
|
||||
PerfKvmCounter hwCycles;
|
||||
std::unique_ptr<PerfKvmCounter> hwCycles;
|
||||
|
||||
/**
|
||||
* Guest instruction counter.
|
||||
@@ -776,7 +779,7 @@ class BaseKvmCPU : public BaseCPU
|
||||
* @see setupInstBreak
|
||||
* @see scheduleInstStop
|
||||
*/
|
||||
PerfKvmCounter hwInstructions;
|
||||
std::unique_ptr<PerfKvmCounter> hwInstructions;
|
||||
|
||||
/**
|
||||
* Does the runTimer control the performance counters?
|
||||
|
||||
@@ -173,12 +173,20 @@ PerfKvmCounter::attach(PerfKvmCounterConfig &config,
|
||||
{
|
||||
if (errno == EACCES)
|
||||
{
|
||||
panic("PerfKvmCounter::attach recieved error EACCESS\n"
|
||||
panic("PerfKvmCounter::attach received error EACCESS.\n"
|
||||
" This error may be caused by a too restrictive setting\n"
|
||||
" in the file '/proc/sys/kernel/perf_event_paranoid'\n"
|
||||
" The default value was changed to 2 in kernel 4.6\n"
|
||||
" in the file '/proc/sys/kernel/perf_event_paranoid'.\n"
|
||||
" The default value was changed to 2 in kernel 4.6.\n"
|
||||
" A value greater than 1 prevents gem5 from making\n"
|
||||
" the syscall to perf_event_open");
|
||||
" the syscall to perf_event_open.\n"
|
||||
" Alternatively, you can set the usePerf flag of the KVM\n"
|
||||
" CPU to False. Setting this flag to False will limit some\n"
|
||||
" functionalities of KVM CPU, such as counting the number of\n"
|
||||
" cycles and the number of instructions, as well as the\n"
|
||||
" ability of exiting to gem5 after a certain amount of cycles\n"
|
||||
" or instructions when using KVM CPU. An example can be found\n"
|
||||
" here, configs/example/gem5_library/"
|
||||
"x86-ubuntu-run-with-kvm-no-perf.py.");
|
||||
}
|
||||
panic("PerfKvmCounter::attach failed (%i)\n", errno);
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
from m5.citations import add_citation
|
||||
from m5.defines import buildEnv
|
||||
from m5.params import *
|
||||
from m5.proxy import *
|
||||
@@ -130,7 +131,7 @@ class ComputeUnit(ClockedObject):
|
||||
# Wavefront size is 64. This is configurable, however changing
|
||||
# this value to anything other than 64 will likely cause errors.
|
||||
wf_size = Param.Int(64, "Wavefront size (in work items)")
|
||||
num_barrier_slots = Param.Int(4, "Number of barrier slots in a CU")
|
||||
num_barrier_slots = Param.Int(16, "Number of barrier slots in a CU")
|
||||
num_SIMDs = Param.Int(4, "number of SIMD units per CU")
|
||||
num_scalar_cores = Param.Int(1, "number of Scalar cores per CU")
|
||||
num_scalar_mem_pipes = Param.Int(
|
||||
@@ -356,3 +357,35 @@ class StorageClassType(Enum):
|
||||
"SC_ARG",
|
||||
"SC_NONE",
|
||||
]
|
||||
|
||||
|
||||
add_citation(
|
||||
ComputeUnit,
|
||||
"""@inproceedings{Gutierrez:2018:amdgpu,
|
||||
author = {Anthony Gutierrez and
|
||||
Bradford M. Beckmann and
|
||||
Alexandru Dutu and
|
||||
Joseph Gross and
|
||||
Michael LeBeane and
|
||||
John Kalamatianos and
|
||||
Onur Kayiran and
|
||||
Matthew Poremba and
|
||||
Brandon Potter and
|
||||
Sooraj Puthoor and
|
||||
Matthew D. Sinclair and
|
||||
Mark Wyse and
|
||||
Jieming Yin and
|
||||
Xianwei Zhang and
|
||||
Akshay Jain and
|
||||
Timothy G. Rogers},
|
||||
title = {Lost in Abstraction: Pitfalls of Analyzing GPUs at the Intermediate
|
||||
Language Level},
|
||||
booktitle = {{IEEE} International Symposium on High Performance Computer Architecture,
|
||||
{HPCA} 2018, Vienna, Austria, February 24-28, 2018},
|
||||
pages = {608--619},
|
||||
publisher = {{IEEE} Computer Society},
|
||||
year = {2018},
|
||||
url = {https://doi.org/10.1109/HPCA.2018.00058},
|
||||
doi = {10.1109/HPCA.2018.00058}
|
||||
}""",
|
||||
)
|
||||
|
||||
@@ -33,6 +33,8 @@
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
from citations import add_citation
|
||||
|
||||
from m5.params import *
|
||||
from m5.objects.AbstractMemory import *
|
||||
|
||||
@@ -56,3 +58,22 @@ class DRAMSim2(AbstractMemory):
|
||||
)
|
||||
traceFile = Param.String("", "Output file for trace generation")
|
||||
enableDebug = Param.Bool(False, "Enable DRAMSim2 debug output")
|
||||
|
||||
|
||||
add_citation(
|
||||
DRAMSim2,
|
||||
"""@article{Rosenfeld:2011:dramsim2,
|
||||
author = {Paul Rosenfeld and
|
||||
Elliott Cooper{-}Balis and
|
||||
Bruce L. Jacob},
|
||||
title = {DRAMSim2: {A} Cycle Accurate Memory System Simulator},
|
||||
journal = {{IEEE} Compututer Architecture Letters},
|
||||
volume = {10},
|
||||
number = {1},
|
||||
pages = {16--19},
|
||||
year = {2011},
|
||||
url = {https://doi.org/10.1109/L-CA.2011.4},
|
||||
doi = {10.1109/L-CA.2011.4}
|
||||
}
|
||||
""",
|
||||
)
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
from m5.citations import add_citation
|
||||
|
||||
from m5.SimObject import *
|
||||
from m5.params import *
|
||||
from m5.proxy import *
|
||||
@@ -41,3 +43,30 @@ class DRAMSys(AbstractMemory):
|
||||
configuration = Param.String("Path to the DRAMSys configuration")
|
||||
resource_directory = Param.String("Path to the DRAMSys resource directory")
|
||||
recordable = Param.Bool(True, "Whether DRAMSys should record a trace file")
|
||||
|
||||
|
||||
add_citation(
|
||||
DRAMSys,
|
||||
"""@inproceedings{Steiner:2020:dramsys4,
|
||||
author = {Lukas Steiner and
|
||||
Matthias Jung and
|
||||
Felipe S. Prado and
|
||||
Kirill Bykov and
|
||||
Norbert Wehn},
|
||||
editor = {Alex Orailoglu and
|
||||
Matthias Jung and
|
||||
Marc Reichenbach},
|
||||
title = {DRAMSys4.0: {A} Fast and Cycle-Accurate SystemC/TLM-Based {DRAM} Simulator},
|
||||
booktitle = {Embedded Computer Systems: Architectures, Modeling, and Simulation
|
||||
- 20th International Conference, {SAMOS} 2020, Samos, Greece, July
|
||||
5-9, 2020, Proceedings},
|
||||
series = {Lecture Notes in Computer Science},
|
||||
volume = {12471},
|
||||
pages = {110--126},
|
||||
publisher = {Springer},
|
||||
year = {2020},
|
||||
url = {https://doi.org/10.1007/978-3-030-60939-9\_8},
|
||||
doi = {10.1007/978-3-030-60939-9\_8}
|
||||
}
|
||||
""",
|
||||
)
|
||||
|
||||
@@ -33,6 +33,8 @@
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
from m5.citations import add_citation
|
||||
|
||||
from m5.params import *
|
||||
from m5.objects.AbstractMemory import *
|
||||
|
||||
@@ -54,3 +56,24 @@ class DRAMsim3(AbstractMemory):
|
||||
filePath = Param.String(
|
||||
"ext/dramsim3/DRAMsim3/", "Directory to prepend to file names"
|
||||
)
|
||||
|
||||
|
||||
add_citation(
|
||||
DRAMsim3,
|
||||
"""@article{Li:2020:dramsim3,
|
||||
author = {Shang Li and
|
||||
Zhiyuan Yang and
|
||||
Dhiraj Reddy and
|
||||
Ankur Srivastava and
|
||||
Bruce L. Jacob},
|
||||
title = {DRAMsim3: {A} Cycle-Accurate, Thermal-Capable {DRAM} Simulator},
|
||||
journal = {{IEEE} Compututer Architecture Letters},
|
||||
volume = {19},
|
||||
number = {2},
|
||||
pages = {110--113},
|
||||
year = {2020},
|
||||
url = {https://doi.org/10.1109/LCA.2020.2973991},
|
||||
doi = {10.1109/LCA.2020.2973991}
|
||||
}
|
||||
""",
|
||||
)
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
from m5.params import *
|
||||
from m5.proxy import *
|
||||
from m5.objects.QoSMemCtrl import *
|
||||
from m5.citations import add_citation
|
||||
|
||||
# Enum for memory scheduling algorithms, currently First-Come
|
||||
# First-Served and a First-Row Hit then First-Come First-Served
|
||||
@@ -99,3 +100,24 @@ class MemCtrl(QoSMemCtrl):
|
||||
|
||||
command_window = Param.Latency("10ns", "Static backend latency")
|
||||
disable_sanity_check = Param.Bool(False, "Disable port resp Q size check")
|
||||
|
||||
|
||||
add_citation(
|
||||
MemCtrl,
|
||||
"""@inproceedings{Hansson:2014:dram-controller,
|
||||
author = {Andreas Hansson and
|
||||
Neha Agarwal and
|
||||
Aasheesh Kolli and
|
||||
Thomas F. Wenisch and
|
||||
Aniruddha N. Udipi},
|
||||
title = {Simulating {DRAM} controllers for future system architecture exploration},
|
||||
booktitle = {2014 {IEEE} International Symposium on Performance Analysis of Systems
|
||||
and Software, {ISPASS} 2014, Monterey, CA, USA, March 23-25, 2014},
|
||||
pages = {201--210},
|
||||
publisher = {{IEEE} Computer Society},
|
||||
year = {2014},
|
||||
url = {https://doi.org/10.1109/ISPASS.2014.6844484},
|
||||
doi = {10.1109/ISPASS.2014.6844484}
|
||||
}
|
||||
""",
|
||||
)
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
# Author: Tushar Krishna
|
||||
#
|
||||
|
||||
from m5.citations import add_citation
|
||||
from m5.params import *
|
||||
from m5.proxy import *
|
||||
from m5.objects.Network import RubyNetwork
|
||||
@@ -83,3 +84,40 @@ class GarnetRouter(BasicRouter):
|
||||
width = Param.UInt32(
|
||||
Parent.ni_flit_size, "bit width supported by the router"
|
||||
)
|
||||
|
||||
|
||||
add_citation(
|
||||
GarnetNetwork,
|
||||
"""@inproceedings{Bharadwaj:2020:kite,
|
||||
author = {Srikant Bharadwaj and
|
||||
Jieming Yin and
|
||||
Bradford M. Beckmann and
|
||||
Tushar Krishna},
|
||||
title = {Kite: {A} Family of Heterogeneous Interposer Topologies Enabled via
|
||||
Accurate Interconnect Modeling},
|
||||
booktitle = {57th {ACM/IEEE} Design Automation Conference, {DAC} 2020, San Francisco,
|
||||
CA, USA, July 20-24, 2020},
|
||||
pages = {1--6},
|
||||
publisher = {{IEEE}},
|
||||
year = {2020},
|
||||
url = {https://doi.org/10.1109/DAC18072.2020.9218539},
|
||||
doi = {10.1109/DAC18072.2020.9218539}
|
||||
}
|
||||
@inproceedings{Agarwal:2009:garnet,
|
||||
author = {Niket Agarwal and
|
||||
Tushar Krishna and
|
||||
Li{-}Shiuan Peh and
|
||||
Niraj K. Jha},
|
||||
title = {{GARNET:} {A} detailed on-chip network model inside a full-system
|
||||
simulator},
|
||||
booktitle = {{IEEE} International Symposium on Performance Analysis of Systems
|
||||
and Software, {ISPASS} 2009, April 26-28, 2009, Boston, Massachusetts,
|
||||
USA, Proceedings},
|
||||
pages = {33--42},
|
||||
publisher = {{IEEE} Computer Society},
|
||||
year = {2009},
|
||||
url = {https://doi.org/10.1109/ISPASS.2009.4919636},
|
||||
doi = {10.1109/ISPASS.2009.4919636}
|
||||
}
|
||||
""",
|
||||
)
|
||||
|
||||
@@ -51,7 +51,7 @@ flit::flit(int packet_id, int id, int vc, int vnet, RouteInfo route, int size,
|
||||
m_enqueue_time = curTime;
|
||||
m_dequeue_time = curTime;
|
||||
m_time = curTime;
|
||||
m_packet_id = id;
|
||||
m_packet_id = packet_id;
|
||||
m_id = id;
|
||||
m_vnet = vnet;
|
||||
m_vc = vc;
|
||||
|
||||
@@ -61,6 +61,7 @@ machine(MachineType:TCC, "TCC Cache")
|
||||
WrVicBlkBack, desc="L1 Write Through(dirty cache)";
|
||||
WrVicBlkEvict, desc="L1 Write Through(dirty cache) and evict";
|
||||
Atomic, desc="Atomic Op";
|
||||
AtomicPassOn, desc="Atomic Op Passed on to Directory";
|
||||
AtomicDone, desc="AtomicOps Complete";
|
||||
AtomicNotDone, desc="AtomicOps not Complete";
|
||||
Data, desc="data messgae";
|
||||
@@ -81,6 +82,7 @@ machine(MachineType:TCC, "TCC Cache")
|
||||
I, AccessPermission:Invalid, desc="Invalid";
|
||||
IV, AccessPermission:Busy, desc="Waiting for Data";
|
||||
WI, AccessPermission:Busy, desc="Waiting on Writethrough Ack";
|
||||
WIB, AccessPermission:Busy, desc="Waiting on Writethrough Ack; Will be Bypassed";
|
||||
A, AccessPermission:Busy, desc="Invalid waiting on atomici Data";
|
||||
}
|
||||
|
||||
@@ -289,7 +291,14 @@ machine(MachineType:TCC, "TCC Cache")
|
||||
is_slc_set := tbe.isSLCSet;
|
||||
}
|
||||
|
||||
if (is_slc_set) {
|
||||
// Whether the SLC bit is set or not, WB acks should invoke the
|
||||
// WBAck event. For cases where a read response will follow a
|
||||
// WBAck (A read bypass evict on a dirty line), the line's TLB
|
||||
// will not be deallocated on WBAck, and the SLC bit will be
|
||||
// checked when the read response is received.
|
||||
if (in_msg.Type == CoherenceResponseType:NBSysWBAck) {
|
||||
trigger(Event:WBAck, in_msg.addr, cache_entry, tbe);
|
||||
} else if (is_slc_set) {
|
||||
// If the SLC bit is set, the response needs to bypass the cache
|
||||
// and should not be allocated an entry.
|
||||
trigger(Event:Bypass, in_msg.addr, cache_entry, tbe);
|
||||
@@ -300,8 +309,6 @@ machine(MachineType:TCC, "TCC Cache")
|
||||
Addr victim := L2cache.cacheProbe(in_msg.addr);
|
||||
trigger(Event:L2_Repl, victim, getCacheEntry(victim), TBEs.lookup(victim));
|
||||
}
|
||||
} else if (in_msg.Type == CoherenceResponseType:NBSysWBAck) {
|
||||
trigger(Event:WBAck, in_msg.addr, cache_entry, tbe);
|
||||
} else {
|
||||
error("Unexpected Response Message to Core");
|
||||
}
|
||||
@@ -349,11 +356,17 @@ machine(MachineType:TCC, "TCC Cache")
|
||||
trigger(Event:WrVicBlk, in_msg.addr, cache_entry, tbe);
|
||||
}
|
||||
} else if (in_msg.Type == CoherenceRequestType:Atomic) {
|
||||
// Currently the Atomic requests do not have GLC/SLC bit handing
|
||||
// support. The assert ensures that the requests do not have
|
||||
// these set, and therefore do not expect to bypass the cache
|
||||
assert(!in_msg.isSLCSet);
|
||||
trigger(Event:Atomic, in_msg.addr, cache_entry, tbe);
|
||||
// If the request is system-level, or if the address isn't in the cache,
|
||||
// then send the request to the directory. Since non-SLC atomics won't be
|
||||
// performed by the directory, TCC will perform the atomic on the return path
|
||||
// on Event:Data.
|
||||
// The action will invalidate the cache line if SLC is set and the address is
|
||||
// in the cache.
|
||||
if(in_msg.isSLCSet || !presentOrAvail(in_msg.addr)) {
|
||||
trigger(Event:AtomicPassOn, in_msg.addr, cache_entry, tbe);
|
||||
} else {
|
||||
trigger(Event:Atomic, in_msg.addr, cache_entry, tbe);
|
||||
}
|
||||
} else if (in_msg.Type == CoherenceRequestType:RdBlk) {
|
||||
if (in_msg.isSLCSet) {
|
||||
// If SLC bit is set, the request needs to go directly to memory.
|
||||
@@ -496,6 +509,22 @@ machine(MachineType:TCC, "TCC Cache")
|
||||
}
|
||||
|
||||
action(ar_sendAtomicResponse, "ar", desc="send Atomic Ack") {
|
||||
peek(coreRequestNetwork_in, CPURequestMsg) {
|
||||
enqueue(responseToCore_out, ResponseMsg, l2_response_latency) {
|
||||
out_msg.addr := address;
|
||||
out_msg.Type := CoherenceResponseType:TDSysResp;
|
||||
out_msg.Destination.clear();
|
||||
out_msg.Destination.add(in_msg.Requestor);
|
||||
out_msg.Sender := machineID;
|
||||
out_msg.MessageSize := MessageSizeType:Response_Data;
|
||||
out_msg.DataBlk := cache_entry.DataBlk;
|
||||
out_msg.isGLCSet := in_msg.isGLCSet;
|
||||
out_msg.isSLCSet := in_msg.isSLCSet;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
action(bar_sendBypassedAtomicResponse, "bar", desc="send bypassed Atomic Ack") {
|
||||
peek(responseFromNB_in, ResponseMsg) {
|
||||
enqueue(responseToCore_out, ResponseMsg, l2_response_latency) {
|
||||
out_msg.addr := address;
|
||||
@@ -608,6 +637,8 @@ machine(MachineType:TCC, "TCC Cache")
|
||||
out_msg.Type := CoherenceRequestType:Atomic;
|
||||
out_msg.Dirty := true;
|
||||
out_msg.writeMask.orMask(in_msg.writeMask);
|
||||
out_msg.isGLCSet := in_msg.isGLCSet;
|
||||
out_msg.isSLCSet := in_msg.isSLCSet;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -682,6 +713,10 @@ machine(MachineType:TCC, "TCC Cache")
|
||||
triggerQueue_in.dequeue(clockEdge());
|
||||
}
|
||||
|
||||
action(pa_performAtomic, "pa", desc="Perform atomic") {
|
||||
cache_entry.DataBlk.atomicPartial(cache_entry.DataBlk, cache_entry.writeMask);
|
||||
}
|
||||
|
||||
// END ACTIONS
|
||||
|
||||
// BEGIN TRANSITIONS
|
||||
@@ -693,7 +728,13 @@ machine(MachineType:TCC, "TCC Cache")
|
||||
// Stalling transitions do NOT check the tag array...and if they do,
|
||||
// they can cause a resource stall deadlock!
|
||||
|
||||
transition(WI, {RdBlk, WrVicBlk, Atomic, WrVicBlkBack}) { //TagArrayRead} {
|
||||
transition(WI, {RdBlk, WrVicBlk, Atomic, AtomicPassOn, WrVicBlkBack}) { //TagArrayRead} {
|
||||
// by putting the stalled requests in a buffer, we reduce resource contention
|
||||
// since they won't try again every cycle and will instead only try again once
|
||||
// woken up
|
||||
st_stallAndWaitRequest;
|
||||
}
|
||||
transition(WIB, {RdBlk, WrVicBlk, Atomic, WrVicBlkBack}) { //TagArrayRead} {
|
||||
// by putting the stalled requests in a buffer, we reduce resource contention
|
||||
// since they won't try again every cycle and will instead only try again once
|
||||
// woken up
|
||||
@@ -705,18 +746,21 @@ machine(MachineType:TCC, "TCC Cache")
|
||||
// woken up
|
||||
st_stallAndWaitRequest;
|
||||
}
|
||||
transition(IV, {WrVicBlk, Atomic, WrVicBlkBack}) { //TagArrayRead} {
|
||||
|
||||
transition(IV, {WrVicBlk, Atomic, AtomicPassOn, WrVicBlkBack}) { //TagArrayRead} {
|
||||
// by putting the stalled requests in a buffer, we reduce resource contention
|
||||
// since they won't try again every cycle and will instead only try again once
|
||||
// woken up
|
||||
st_stallAndWaitRequest;
|
||||
}
|
||||
|
||||
transition({M, V}, RdBlk) {TagArrayRead, DataArrayRead} {
|
||||
p_profileHit;
|
||||
sd_sendData;
|
||||
ut_updateTag;
|
||||
p_popRequestQueue;
|
||||
}
|
||||
|
||||
transition(W, RdBlk, WI) {TagArrayRead, DataArrayRead} {
|
||||
t_allocateTBE;
|
||||
wb_writeBack;
|
||||
@@ -751,7 +795,7 @@ machine(MachineType:TCC, "TCC Cache")
|
||||
// Transition to be called when a read request with SLC flag set arrives at
|
||||
// entry in state W. It evicts and invalidates the cache entry before
|
||||
// forwarding the request to global memory
|
||||
transition(W, RdBypassEvict, I) {TagArrayRead} {
|
||||
transition(W, RdBypassEvict, WIB) {TagArrayRead} {
|
||||
p_profileMiss;
|
||||
t_allocateTBE;
|
||||
wb_writeBack;
|
||||
@@ -763,7 +807,7 @@ machine(MachineType:TCC, "TCC Cache")
|
||||
// Transition to be called when a read request with SLC flag set arrives at
|
||||
// entry in state M. It evicts and invalidates the cache entry before
|
||||
// forwarding the request to global memory to main memory
|
||||
transition(M, RdBypassEvict, I) {TagArrayRead} {
|
||||
transition(M, RdBypassEvict, WIB) {TagArrayRead} {
|
||||
p_profileMiss;
|
||||
t_allocateTBE;
|
||||
wb_writeBack;
|
||||
@@ -785,25 +829,25 @@ machine(MachineType:TCC, "TCC Cache")
|
||||
|
||||
// Transition to be called when a read request with SLC flag arrives at entry
|
||||
// in transient state. The request stalls until the pending transition is complete.
|
||||
transition({WI, IV}, RdBypassEvict) {
|
||||
transition({WI, WIB, IV}, RdBypassEvict) {
|
||||
st_stallAndWaitRequest;
|
||||
}
|
||||
|
||||
transition(V, Atomic, A) {TagArrayRead} {
|
||||
transition(V, Atomic, M) {TagArrayRead, DataArrayWrite} {
|
||||
p_profileHit;
|
||||
i_invL2;
|
||||
t_allocateTBE;
|
||||
at_atomicThrough;
|
||||
ina_incrementNumAtomics;
|
||||
wdb_writeDirtyBytes;
|
||||
pa_performAtomic;
|
||||
ar_sendAtomicResponse;
|
||||
p_popRequestQueue;
|
||||
}
|
||||
|
||||
transition(I, Atomic, A) {TagArrayRead} {
|
||||
transition(I, Atomic, M) {TagArrayRead, TagArrayWrite, DataArrayWrite} {
|
||||
p_profileMiss;
|
||||
i_invL2;
|
||||
t_allocateTBE;
|
||||
at_atomicThrough;
|
||||
ina_incrementNumAtomics;
|
||||
a_allocateBlock;
|
||||
ut_updateTag;
|
||||
wdb_writeDirtyBytes;
|
||||
pa_performAtomic;
|
||||
ar_sendAtomicResponse;
|
||||
p_popRequestQueue;
|
||||
}
|
||||
|
||||
@@ -815,7 +859,45 @@ transition(I, Atomic, A) {TagArrayRead} {
|
||||
st_stallAndWaitRequest;
|
||||
}
|
||||
|
||||
transition({M, W}, Atomic, WI) {TagArrayRead} {
|
||||
transition({M, W}, Atomic) {TagArrayRead, TagArrayWrite, DataArrayWrite} {
|
||||
p_profileHit;
|
||||
wdb_writeDirtyBytes;
|
||||
pa_performAtomic;
|
||||
ar_sendAtomicResponse;
|
||||
p_popRequestQueue;
|
||||
}
|
||||
|
||||
// The following atomic pass on actions will send the request to the directory,
|
||||
// and are triggered when an atomic request is received that is not in TCC,
|
||||
// and/or if SLC is set.
|
||||
|
||||
transition(V, AtomicPassOn, A) {TagArrayRead} {
|
||||
p_profileHit;
|
||||
i_invL2;
|
||||
t_allocateTBE;
|
||||
at_atomicThrough;
|
||||
ina_incrementNumAtomics;
|
||||
p_popRequestQueue;
|
||||
}
|
||||
|
||||
transition(I, AtomicPassOn, A) {TagArrayRead} {
|
||||
p_profileMiss;
|
||||
i_invL2;
|
||||
t_allocateTBE;
|
||||
at_atomicThrough;
|
||||
ina_incrementNumAtomics;
|
||||
p_popRequestQueue;
|
||||
}
|
||||
|
||||
transition(A, AtomicPassOn) {
|
||||
p_profileMiss;
|
||||
// by putting the stalled requests in a buffer, we reduce resource contention
|
||||
// since they won't try again every cycle and will instead only try again once
|
||||
// woken up
|
||||
st_stallAndWaitRequest;
|
||||
}
|
||||
|
||||
transition({M, W}, AtomicPassOn, WI) {TagArrayRead} {
|
||||
t_allocateTBE;
|
||||
wb_writeBack;
|
||||
// after writing back the current line, we need to wait for it to be done
|
||||
@@ -900,7 +982,7 @@ transition(I, Atomic, A) {TagArrayRead} {
|
||||
i_invL2;
|
||||
}
|
||||
|
||||
transition({A, IV, WI}, L2_Repl) {
|
||||
transition({A, IV, WI, WIB}, L2_Repl) {
|
||||
i_invL2;
|
||||
}
|
||||
|
||||
@@ -919,7 +1001,7 @@ transition(I, Atomic, A) {TagArrayRead} {
|
||||
pp_popProbeQueue;
|
||||
}
|
||||
|
||||
transition({A, IV, WI}, PrbInv) {
|
||||
transition({A, IV, WI, WIB}, PrbInv) {
|
||||
pi_sendProbeResponseInv;
|
||||
pp_popProbeQueue;
|
||||
}
|
||||
@@ -934,6 +1016,18 @@ transition(I, Atomic, A) {TagArrayRead} {
|
||||
dt_deallocateTBE;
|
||||
}
|
||||
|
||||
transition(A, Bypass) {TagArrayRead, TagArrayWrite, DataArrayWrite} {
|
||||
bar_sendBypassedAtomicResponse;
|
||||
dna_decrementNumAtomics;
|
||||
pr_popResponseQueue;
|
||||
}
|
||||
|
||||
transition(WI, Bypass, I) {
|
||||
pr_popResponseQueue;
|
||||
wada_wakeUpAllDependentsAddr;
|
||||
dt_deallocateTBE;
|
||||
}
|
||||
|
||||
transition(IV, Data, V) {TagArrayRead, TagArrayWrite, DataArrayWrite} {
|
||||
a_allocateBlock;
|
||||
ut_updateTag;
|
||||
@@ -944,9 +1038,10 @@ transition(I, Atomic, A) {TagArrayRead} {
|
||||
dt_deallocateTBE;
|
||||
}
|
||||
|
||||
transition(A, Data) {TagArrayRead, TagArrayWrite, DataArrayWrite} {
|
||||
transition(A, Data, M) {TagArrayRead, TagArrayWrite, DataArrayWrite} {
|
||||
a_allocateBlock;
|
||||
ar_sendAtomicResponse;
|
||||
pa_performAtomic;
|
||||
bar_sendBypassedAtomicResponse;
|
||||
dna_decrementNumAtomics;
|
||||
pr_popResponseQueue;
|
||||
}
|
||||
@@ -974,4 +1069,8 @@ transition(I, Atomic, A) {TagArrayRead} {
|
||||
wada_wakeUpAllDependentsAddr;
|
||||
pr_popResponseQueue;
|
||||
}
|
||||
|
||||
transition(WIB, WBAck,I) {
|
||||
pr_popResponseQueue;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,6 +161,7 @@ machine(MachineType:Directory, "AMD Baseline protocol")
|
||||
uint64_t probe_id, desc="probe id for lifetime profiling";
|
||||
WriteMask writeMask, desc="outstanding write through mask";
|
||||
int Len, desc="Length of memory request for DMA";
|
||||
bool isSLCSet, desc="Bypass L1 and L2 Cache";
|
||||
}
|
||||
|
||||
structure(TBETable, external="yes") {
|
||||
@@ -975,6 +976,7 @@ machine(MachineType:Directory, "AMD Baseline protocol")
|
||||
tbe.atomicData := true;
|
||||
tbe.WTRequestor := in_msg.WTRequestor;
|
||||
tbe.LastSender := in_msg.Requestor;
|
||||
tbe.isSLCSet := in_msg.isSLCSet;
|
||||
}
|
||||
tbe.Dirty := false;
|
||||
if (in_msg.Type == CoherenceRequestType:WriteThrough) {
|
||||
@@ -995,7 +997,11 @@ machine(MachineType:Directory, "AMD Baseline protocol")
|
||||
|
||||
action(wd_writeBackData, "wd", desc="Write back data if needed") {
|
||||
if (tbe.wtData || tbe.atomicData || tbe.Dirty == false) {
|
||||
if (tbe.atomicData) {
|
||||
// If SLC is not set, the atomic is handled in the L2
|
||||
// Atomic needs to be done at the L3 only if this is
|
||||
// not the case
|
||||
|
||||
if (tbe.atomicData && tbe.isSLCSet) {
|
||||
tbe.DataBlk.atomicPartial(tbe.DataBlk, tbe.writeMask);
|
||||
}
|
||||
enqueue(memQueue_out, MemoryMsg, to_memory_controller_latency) {
|
||||
|
||||
@@ -50,14 +50,6 @@ with gem5_scons.Configure(main) as conf:
|
||||
warning('protoc version', min_protoc_version, 'or newer required.\n'
|
||||
'Installed version:', protoc_version[1])
|
||||
else:
|
||||
# Attempt to determine the appropriate include path and
|
||||
# library path using pkg-config, that means we also need to
|
||||
# check for pkg-config. Note that it is possible to use
|
||||
# protobuf without the involvement of pkg-config. Later on we
|
||||
# check go a library config check and at that point the test
|
||||
# will fail if libprotobuf cannot be found.
|
||||
if conf.env['HAVE_PKG_CONFIG']:
|
||||
conf.CheckPkgConfig('protobuf', '--cflags', '--libs-only-L')
|
||||
conf.env['HAVE_PROTOC'] = True
|
||||
|
||||
# If we have the protobuf compiler, also make sure we have the
|
||||
@@ -65,9 +57,11 @@ with gem5_scons.Configure(main) as conf:
|
||||
# automatically added to the LIBS environment variable. After
|
||||
# this, we can use the HAVE_PROTOBUF flag to determine if we have
|
||||
# got both protoc and libprotobuf available.
|
||||
conf.env['CONF']['HAVE_PROTOBUF'] = conf.env['HAVE_PROTOC'] and \
|
||||
conf.env['CONF']['HAVE_PROTOBUF'] = conf.env['HAVE_PROTOC'] and (
|
||||
(conf.env['HAVE_PKG_CONFIG'] and
|
||||
conf.CheckPkgConfig('protobuf', '--cflags', '--libs')) or
|
||||
conf.CheckLibWithHeader('protobuf', 'google/protobuf/message.h',
|
||||
'C++', 'GOOGLE_PROTOBUF_VERIFY_VERSION;')
|
||||
'C++', 'GOOGLE_PROTOBUF_VERIFY_VERSION;'))
|
||||
|
||||
# If we have the compiler but not the library, print another warning.
|
||||
if main['HAVE_PROTOC'] and not main['CONF']['HAVE_PROTOBUF']:
|
||||
|
||||
@@ -311,6 +311,7 @@ PySource('gem5.utils.multiprocessing',
|
||||
PySource('', 'importer.py')
|
||||
PySource('m5', 'm5/__init__.py')
|
||||
PySource('m5', 'm5/SimObject.py')
|
||||
PySource('m5', 'm5/citations.py')
|
||||
PySource('m5', 'm5/core.py')
|
||||
PySource('m5', 'm5/debug.py')
|
||||
PySource('m5', 'm5/event.py')
|
||||
|
||||
@@ -285,19 +285,21 @@ class ClientWrapper:
|
||||
return False
|
||||
if (
|
||||
gem5_version
|
||||
and not gem5_version.upper().startswith("DEVELOP")
|
||||
and not self._get_resources_compatible_with_gem5_version(
|
||||
[resource], gem5_version=gem5_version
|
||||
)
|
||||
):
|
||||
warn(
|
||||
f"Resource {resource['id']} with version "
|
||||
f"{resource['resource_version']} is not known to be compatible"
|
||||
f" with gem5 version {gem5_version}. "
|
||||
"This may cause problems with your simulation. "
|
||||
"This resource's compatibility "
|
||||
"with different gem5 versions can be found here: "
|
||||
"https://resources.gem5.org"
|
||||
f"/resources/{resource['id']}/versions"
|
||||
)
|
||||
if not gem5_version.upper().startswith("DEVELOP"):
|
||||
warn(
|
||||
f"Resource {resource['id']} with version "
|
||||
f"{resource['resource_version']} is not known to be compatible"
|
||||
f" with gem5 version {gem5_version}. "
|
||||
"This may cause problems with your simulation. "
|
||||
"This resource's compatibility "
|
||||
"with different gem5 versions can be found here: "
|
||||
"https://resources.gem5.org"
|
||||
f"/resources/{resource['id']}/versions"
|
||||
)
|
||||
return False
|
||||
return True
|
||||
|
||||
@@ -52,7 +52,7 @@ class AbstractWorkload:
|
||||
workload = CustomWorkload(
|
||||
function = "set_se_binary_workload",
|
||||
parameters = {
|
||||
"binary" : Resource("x86-print-this"),
|
||||
"binary" : obtain_resource("x86-print-this"),
|
||||
"arguments" : ["hello", 6]
|
||||
},
|
||||
)
|
||||
@@ -64,7 +64,7 @@ class AbstractWorkload:
|
||||
|
||||
```py
|
||||
board.set_se_binary_workload(
|
||||
binary = Resource("x86-print-this"),
|
||||
binary = obtain_resource("x86-print-this"),
|
||||
arguments = ["hello", 6],
|
||||
)
|
||||
```
|
||||
@@ -121,7 +121,7 @@ class CustomWorkload(AbstractWorkload):
|
||||
workload = CustomWorkload(
|
||||
function = "set_se_binary_workload",
|
||||
parameters = {
|
||||
"binary" : Resource("x86-print-this"),
|
||||
"binary" : obtain_resource("x86-print-this"),
|
||||
"arguments" : ["hello", 6]
|
||||
},
|
||||
)
|
||||
@@ -148,7 +148,9 @@ class Workload(AbstractWorkload):
|
||||
|
||||
# Optionally we can override a parameter in the workload. In this example
|
||||
# we are going to run this workload with a difference kernel.
|
||||
workload.set_parameter("kernel", Resource("arm64-linux-kernel-4.14.134"))
|
||||
workload.set_parameter("kernel",
|
||||
obtain_resource("arm64-linux-kernel-4.14.134")
|
||||
)
|
||||
|
||||
# We then set this workload to the board.
|
||||
board.set_workload(workload)
|
||||
@@ -193,8 +195,8 @@ class Workload(AbstractWorkload):
|
||||
|
||||
```python
|
||||
board.set_kernel_disk_workload(
|
||||
kernel = Resource("x86-linux-kernel-5.4.49"),
|
||||
disk-image = Resource("x86-ubuntu-18.04-img"),
|
||||
kernel = obtain_resource("x86-linux-kernel-5.4.49"),
|
||||
disk-image = obtain_resource("x86-ubuntu-18.04-img"),
|
||||
readfile_contents = "m5_exit; echo 'hello'; m5_exit",
|
||||
)
|
||||
```
|
||||
|
||||
@@ -48,8 +48,8 @@ def run_sim(name):
|
||||
from gem5.simulate.simulator import Simulator
|
||||
board = X86DemoBoard()
|
||||
board.set_kernel_disk_workload(
|
||||
kernel=Resource("x86-linux-kernel-5.4.49"),
|
||||
disk_image=Resource("x86-ubuntu-18.04-img"),
|
||||
kernel=obtain_resource("x86-linux-kernel-5.4.49"),
|
||||
disk_image=obtain_resource("x86-ubuntu-18.04-img"),
|
||||
)
|
||||
simulator = Simulator(board=board)
|
||||
simulator.run(max_ticks=10000000)
|
||||
|
||||
@@ -47,6 +47,8 @@ import m5
|
||||
from m5.util import *
|
||||
from m5.util.pybind import *
|
||||
|
||||
from m5.citations import gem5_citations
|
||||
|
||||
# Use the pyfdt and not the helper class, because the fdthelper
|
||||
# relies on the SimObject definition
|
||||
from m5.ext.pyfdt import pyfdt
|
||||
@@ -215,6 +217,8 @@ class MetaSimObject(type):
|
||||
cls._instantiated = False # really instantiated, cloned, or subclassed
|
||||
cls._init_called = False # Used to check if __init__ overridden
|
||||
|
||||
cls._citations = gem5_citations # Default to gem5's citations
|
||||
|
||||
# We don't support multiple inheritance of sim objects. If you want
|
||||
# to, you must fix multidict to deal with it properly. Non sim-objects
|
||||
# are ok, though
|
||||
|
||||
191
src/python/m5/citations.py
Normal file
191
src/python/m5/citations.py
Normal file
@@ -0,0 +1,191 @@
|
||||
# Copyright (c) 2023 The Regents of The University of California
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met: redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer;
|
||||
# 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;
|
||||
# neither the name of the copyright holders 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
|
||||
# OWNER 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.
|
||||
|
||||
from pathlib import Path
|
||||
from typing import Type
|
||||
|
||||
import m5.options
|
||||
|
||||
|
||||
def add_citation(sim_obj_cls: Type["SimObject"], citation: str):
|
||||
"""Add a citation to a SimObject class.
|
||||
|
||||
:param sim_obj_cls: The SimObject class to add the citation to.
|
||||
:param citation: The citation to add. Should be bibtex compatible
|
||||
entry or entries
|
||||
|
||||
This function will encode the citation into the SimObject class and it
|
||||
will be included in the citations in the output directory when the
|
||||
SimObject is used. If you have multiple citations, then you should include
|
||||
one multiline string with all of the citations.
|
||||
"""
|
||||
|
||||
sim_obj_cls._citations += citation
|
||||
|
||||
|
||||
def gather_citations(root: "SimObject"):
|
||||
"""Based on the root SimObject, walk the object hierarchy and gather all
|
||||
of the citations together and then print them to citations.bib in the
|
||||
output directory.
|
||||
"""
|
||||
|
||||
citations = {}
|
||||
for obj in root.descendants():
|
||||
loc = 0
|
||||
while loc >= 0:
|
||||
key, cite, loc = _get_next_key_entry(obj._citations, loc)
|
||||
# If a key repeats, then just overwrite it
|
||||
citations[key] = cite
|
||||
|
||||
with open(Path(m5.options.outdir) / "citations.bib", "w") as output:
|
||||
output.writelines(citations.values())
|
||||
|
||||
|
||||
def _get_next_key_entry(citations: str, loc: int = 0):
|
||||
"""Return the key, the citation, and the end of the citation location"""
|
||||
|
||||
start = citations.find("@", loc)
|
||||
key_start = citations.find("{", start)
|
||||
key_end = citations.find(",", key_start)
|
||||
end = citations.find("@", start + 1)
|
||||
if end == -1:
|
||||
end = len(citations)
|
||||
next = -1
|
||||
else:
|
||||
next = end
|
||||
|
||||
return citations[key_start:key_end], citations[start:end], next
|
||||
|
||||
|
||||
gem5_citations = """@article{Binkert:2011:gem5,
|
||||
author = {Nathan L. Binkert and
|
||||
Bradford M. Beckmann and
|
||||
Gabriel Black and
|
||||
Steven K. Reinhardt and
|
||||
Ali G. Saidi and
|
||||
Arkaprava Basu and
|
||||
Joel Hestness and
|
||||
Derek Hower and
|
||||
Tushar Krishna and
|
||||
Somayeh Sardashti and
|
||||
Rathijit Sen and
|
||||
Korey Sewell and
|
||||
Muhammad Shoaib Bin Altaf and
|
||||
Nilay Vaish and
|
||||
Mark D. Hill and
|
||||
David A. Wood},
|
||||
title = {The gem5 simulator},
|
||||
journal = {{SIGARCH} Comput. Archit. News},
|
||||
volume = {39},
|
||||
number = {2},
|
||||
pages = {1--7},
|
||||
year = {2011},
|
||||
url = {https://doi.org/10.1145/2024716.2024718},
|
||||
doi = {10.1145/2024716.2024718}
|
||||
}
|
||||
@article{Lowe-Power:2020:gem5-20,
|
||||
author = {Jason Lowe{-}Power and
|
||||
Abdul Mutaal Ahmad and
|
||||
Ayaz Akram and
|
||||
Mohammad Alian and
|
||||
Rico Amslinger and
|
||||
Matteo Andreozzi and
|
||||
Adri{\`{a}} Armejach and
|
||||
Nils Asmussen and
|
||||
Srikant Bharadwaj and
|
||||
Gabe Black and
|
||||
Gedare Bloom and
|
||||
Bobby R. Bruce and
|
||||
Daniel Rodrigues Carvalho and
|
||||
Jer{\'{o}}nimo Castrill{\'{o}}n and
|
||||
Lizhong Chen and
|
||||
Nicolas Derumigny and
|
||||
Stephan Diestelhorst and
|
||||
Wendy Elsasser and
|
||||
Marjan Fariborz and
|
||||
Amin Farmahini Farahani and
|
||||
Pouya Fotouhi and
|
||||
Ryan Gambord and
|
||||
Jayneel Gandhi and
|
||||
Dibakar Gope and
|
||||
Thomas Grass and
|
||||
Bagus Hanindhito and
|
||||
Andreas Hansson and
|
||||
Swapnil Haria and
|
||||
Austin Harris and
|
||||
Timothy Hayes and
|
||||
Adrian Herrera and
|
||||
Matthew Horsnell and
|
||||
Syed Ali Raza Jafri and
|
||||
Radhika Jagtap and
|
||||
Hanhwi Jang and
|
||||
Reiley Jeyapaul and
|
||||
Timothy M. Jones and
|
||||
Matthias Jung and
|
||||
Subash Kannoth and
|
||||
Hamidreza Khaleghzadeh and
|
||||
Yuetsu Kodama and
|
||||
Tushar Krishna and
|
||||
Tommaso Marinelli and
|
||||
Christian Menard and
|
||||
Andrea Mondelli and
|
||||
Tiago M{\"{u}}ck and
|
||||
Omar Naji and
|
||||
Krishnendra Nathella and
|
||||
Hoa Nguyen and
|
||||
Nikos Nikoleris and
|
||||
Lena E. Olson and
|
||||
Marc S. Orr and
|
||||
Binh Pham and
|
||||
Pablo Prieto and
|
||||
Trivikram Reddy and
|
||||
Alec Roelke and
|
||||
Mahyar Samani and
|
||||
Andreas Sandberg and
|
||||
Javier Setoain and
|
||||
Boris Shingarov and
|
||||
Matthew D. Sinclair and
|
||||
Tuan Ta and
|
||||
Rahul Thakur and
|
||||
Giacomo Travaglini and
|
||||
Michael Upton and
|
||||
Nilay Vaish and
|
||||
Ilias Vougioukas and
|
||||
Zhengrong Wang and
|
||||
Norbert Wehn and
|
||||
Christian Weis and
|
||||
David A. Wood and
|
||||
Hongil Yoon and
|
||||
{\'{E}}der F. Zulian},
|
||||
title = {The gem5 Simulator: Version 20.0+},
|
||||
journal = {CoRR},
|
||||
volume = {abs/2007.03152},
|
||||
year = {2020},
|
||||
url = {https://arxiv.org/abs/2007.03152},
|
||||
eprinttype = {arXiv},
|
||||
eprint = {2007.03152}
|
||||
}
|
||||
"""
|
||||
@@ -348,13 +348,14 @@ def interact(scope):
|
||||
|
||||
|
||||
def _check_tracing():
|
||||
import m5
|
||||
import _m5.core
|
||||
|
||||
from .util import fatal
|
||||
|
||||
if _m5.core.TRACING_ON:
|
||||
return
|
||||
|
||||
m5.fatal("Tracing is not enabled. Compile with TRACING_ON")
|
||||
fatal("Tracing is not enabled. Compile with TRACING_ON")
|
||||
|
||||
|
||||
def main():
|
||||
@@ -369,7 +370,7 @@ def main():
|
||||
from . import stats
|
||||
from . import trace
|
||||
|
||||
from .util import inform, fatal, panic, isInteractive
|
||||
from .util import inform, panic, isInteractive
|
||||
from m5.util.terminal_formatter import TerminalFormatter
|
||||
|
||||
options, arguments = parse_options()
|
||||
|
||||
@@ -51,6 +51,7 @@ from . import SimObject
|
||||
from . import ticks
|
||||
from . import objects
|
||||
from . import params
|
||||
from .citations import gather_citations
|
||||
from m5.util.dot_writer import do_dot, do_dvfs_dot
|
||||
from m5.util.dot_writer_ruby import do_ruby_dot
|
||||
|
||||
@@ -164,6 +165,8 @@ def instantiate(ckpt_dir=None):
|
||||
# a checkpoint, If so, this call will shift them to be at a valid time.
|
||||
updateStatEvents()
|
||||
|
||||
gather_citations(root)
|
||||
|
||||
|
||||
need_startup = True
|
||||
|
||||
|
||||
@@ -145,8 +145,11 @@ CheckpointIn::setDir(const std::string &name)
|
||||
// appears to have a format placeholder in it.
|
||||
currentDirectory = (name.find("%") != std::string::npos) ?
|
||||
csprintf(name, curTick()) : name;
|
||||
if (currentDirectory[currentDirectory.size() - 1] != '/')
|
||||
auto isEmptyPath = currentDirectory.empty();
|
||||
auto endsWithSlash = !isEmptyPath && currentDirectory.back() == '/';
|
||||
if (!endsWithSlash) {
|
||||
currentDirectory += "/";
|
||||
}
|
||||
return currentDirectory;
|
||||
}
|
||||
|
||||
|
||||
@@ -18,7 +18,6 @@ images=("gcc-version-12"
|
||||
"gcc-version-10"
|
||||
"gcc-version-9"
|
||||
"gcc-version-8"
|
||||
"gcc-version-7"
|
||||
"clang-version-14"
|
||||
"clang-version-13"
|
||||
"clang-version-12"
|
||||
@@ -27,7 +26,6 @@ images=("gcc-version-12"
|
||||
"clang-version-9"
|
||||
"clang-version-8"
|
||||
"clang-version-7"
|
||||
"clang-version-6.0"
|
||||
# The following checks our support for Ubuntu 18.04, 20.04, and 22.04.
|
||||
"ubuntu-18.04_all-dependencies"
|
||||
"ubuntu-20.04_all-dependencies"
|
||||
|
||||
@@ -36,7 +36,7 @@ Characteristics
|
||||
from gem5.isas import ISA
|
||||
from m5.objects import ArmDefaultRelease
|
||||
from gem5.utils.requires import requires
|
||||
from gem5.resources.resource import Resource
|
||||
from gem5.resources.resource import obtain_resource
|
||||
from gem5.simulate.simulator import Simulator
|
||||
from m5.objects import VExpress_GEM5_Foundation
|
||||
from gem5.coherence_protocol import CoherenceProtocol
|
||||
@@ -199,15 +199,15 @@ board = ArmBoard(
|
||||
|
||||
# Set the Full System workload.
|
||||
board.set_kernel_disk_workload(
|
||||
kernel=Resource(
|
||||
kernel=obtain_resource(
|
||||
"arm64-linux-kernel-5.4.49",
|
||||
resource_directory=args.resource_directory,
|
||||
),
|
||||
bootloader=Resource(
|
||||
bootloader=obtain_resource(
|
||||
"arm64-bootloader-foundation",
|
||||
resource_directory=args.resource_directory,
|
||||
),
|
||||
disk_image=Resource(
|
||||
disk_image=obtain_resource(
|
||||
"arm64-ubuntu-20.04-img",
|
||||
resource_directory=args.resource_directory,
|
||||
),
|
||||
|
||||
@@ -55,7 +55,7 @@ from gem5.components.processors.cpu_types import (
|
||||
from gem5.components.processors.simple_switchable_processor import (
|
||||
SimpleSwitchableProcessor,
|
||||
)
|
||||
from gem5.resources.resource import Resource
|
||||
from gem5.resources.resource import obtain_resource
|
||||
from gem5.runtime import get_runtime_coherence_protocol
|
||||
from gem5.utils.requires import requires
|
||||
|
||||
@@ -179,10 +179,10 @@ kernel_args = motherboard.get_default_kernel_args() + [args.kernel_args]
|
||||
|
||||
# Set the Full System workload.
|
||||
motherboard.set_kernel_disk_workload(
|
||||
kernel=Resource(
|
||||
kernel=obtain_resource(
|
||||
"x86-linux-kernel-5.4.49", resource_directory=args.resource_directory
|
||||
),
|
||||
disk_image=Resource(
|
||||
disk_image=obtain_resource(
|
||||
"x86-ubuntu-18.04-img", resource_directory=args.resource_directory
|
||||
),
|
||||
readfile_contents=dedent(
|
||||
|
||||
@@ -45,7 +45,7 @@ from gem5.components.processors.cpu_types import (
|
||||
from gem5.components.processors.simple_switchable_processor import (
|
||||
SimpleSwitchableProcessor,
|
||||
)
|
||||
from gem5.resources.resource import Resource
|
||||
from gem5.resources.resource import obtain_resource
|
||||
from gem5.runtime import get_runtime_coherence_protocol
|
||||
from gem5.simulate.simulator import Simulator
|
||||
from gem5.simulate.exit_event import ExitEvent
|
||||
@@ -165,10 +165,10 @@ kernal_args = motherboard.get_default_kernel_args() + [args.kernel_args]
|
||||
|
||||
# Set the Full System workload.
|
||||
motherboard.set_kernel_disk_workload(
|
||||
kernel=Resource(
|
||||
kernel=obtain_resource(
|
||||
"x86-linux-kernel-5.4.49", resource_directory=args.resource_directory
|
||||
),
|
||||
disk_image=Resource(
|
||||
disk_image=obtain_resource(
|
||||
"x86-ubuntu-18.04-img", resource_directory=args.resource_directory
|
||||
),
|
||||
# The first exit signals to switch processors.
|
||||
|
||||
@@ -37,7 +37,7 @@ Notes
|
||||
|
||||
import m5.stats
|
||||
|
||||
from gem5.resources.resource import Resource
|
||||
from gem5.resources.resource import obtain_resource
|
||||
from gem5.components.boards.x86_board import X86Board
|
||||
from gem5.components.memory import SingleChannelDDR3_1600
|
||||
from gem5.components.processors.simple_switchable_processor import (
|
||||
@@ -205,10 +205,10 @@ command = (
|
||||
)
|
||||
|
||||
board.set_kernel_disk_workload(
|
||||
kernel=Resource(
|
||||
kernel=obtain_resource(
|
||||
"x86-linux-kernel-5.4.49", resource_directory=args.resource_directory
|
||||
),
|
||||
disk_image=Resource(
|
||||
disk_image=obtain_resource(
|
||||
"x86-parsec", resource_directory=args.resource_directory
|
||||
),
|
||||
readfile_contents=command,
|
||||
|
||||
@@ -30,7 +30,7 @@ The system has no cache heirarchy and is as "bare-bones" as you can get in
|
||||
gem5 while still being functinal.
|
||||
"""
|
||||
|
||||
from gem5.resources.resource import Resource
|
||||
from gem5.resources.resource import obtain_resource
|
||||
from gem5.components.processors.cpu_types import (
|
||||
get_cpu_types_str_set,
|
||||
get_cpu_type_from_str,
|
||||
@@ -135,7 +135,9 @@ motherboard = SimpleBoard(
|
||||
)
|
||||
|
||||
# Set the workload
|
||||
binary = Resource(args.resource, resource_directory=args.resource_directory)
|
||||
binary = obtain_resource(
|
||||
args.resource, resource_directory=args.resource_directory
|
||||
)
|
||||
motherboard.set_se_binary_workload(binary, arguments=args.arguments)
|
||||
|
||||
# Run the simulation
|
||||
|
||||
@@ -45,7 +45,7 @@ By default a generator is passed to define the evit_event. A list of functions
|
||||
can also be passed. This is enabled by passing the `--list-format` flag.
|
||||
"""
|
||||
|
||||
from gem5.resources.resource import Resource
|
||||
from gem5.resources.resource import obtain_resource
|
||||
from gem5.components.memory import SingleChannelDDR3_1600
|
||||
from gem5.components.boards.simple_board import SimpleBoard
|
||||
from gem5.components.cachehierarchies.classic.no_cache import NoCache
|
||||
@@ -101,7 +101,7 @@ motherboard = SimpleBoard(
|
||||
# Set the workload
|
||||
# Note: Here we're using the "x86-m5-exit-repeat" resource. This calls an
|
||||
# `m5_exit(0)` command in an infinite while-loop.
|
||||
binary = Resource(
|
||||
binary = obtain_resource(
|
||||
"x86-m5-exit-repeat", resource_directory=args.resource_directory
|
||||
)
|
||||
motherboard.set_se_binary_workload(binary)
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
|
||||
"""
|
||||
|
||||
from gem5.resources.resource import Resource
|
||||
from gem5.resources.resource import obtain_resource
|
||||
from gem5.isas import ISA
|
||||
from gem5.components.memory import SingleChannelDDR3_1600
|
||||
from gem5.components.boards.simple_board import SimpleBoard
|
||||
@@ -76,7 +76,7 @@ motherboard = SimpleBoard(
|
||||
)
|
||||
|
||||
# Set the workload
|
||||
binary = Resource(
|
||||
binary = obtain_resource(
|
||||
"x86-hello64-static", resource_directory=args.resource_directory
|
||||
)
|
||||
motherboard.set_se_binary_workload(binary)
|
||||
|
||||
@@ -33,7 +33,7 @@ run before, at, or after the running of `simulator.run`.
|
||||
time.
|
||||
"""
|
||||
|
||||
from gem5.resources.resource import Resource
|
||||
from gem5.resources.resource import obtain_resource
|
||||
from gem5.isas import ISA
|
||||
from gem5.components.memory import SingleChannelDDR3_1600
|
||||
from gem5.components.boards.simple_board import SimpleBoard
|
||||
@@ -97,7 +97,7 @@ motherboard = SimpleBoard(
|
||||
)
|
||||
|
||||
# Set the workload
|
||||
binary = Resource(
|
||||
binary = obtain_resource(
|
||||
"x86-hello64-static", resource_directory=args.resource_directory
|
||||
)
|
||||
motherboard.set_se_binary_workload(binary)
|
||||
|
||||
@@ -110,12 +110,6 @@ class TestObtainResourcesCheck(unittest.TestCase):
|
||||
resource_directory=self.get_resource_dir(),
|
||||
resource_version="1.5.0",
|
||||
)
|
||||
self.assertTrue(
|
||||
f"warn: Resource test-binary-resource with version 1.5.0 is not known to be compatible with gem5 version {core.gem5Version}. "
|
||||
"This may cause problems with your simulation. This resource's compatibility with different gem5 versions can be found here: "
|
||||
f"https://resources.gem5.org/resources/test-binary-resource/versions"
|
||||
in f.getvalue()
|
||||
)
|
||||
|
||||
resource = obtain_resource(
|
||||
resource_id="test-binary-resource",
|
||||
|
||||
@@ -72,14 +72,14 @@ class CustomWorkloadTestSuite(unittest.TestCase):
|
||||
)
|
||||
|
||||
def test_get_function_str(self) -> None:
|
||||
# Tests `CustomResource.get_function_str`
|
||||
# Tests `CustomWorkload.get_function_str`
|
||||
|
||||
self.assertEqual(
|
||||
"set_se_binary_workload", self.custom_workload.get_function_str()
|
||||
)
|
||||
|
||||
def test_get_parameters(self) -> None:
|
||||
# Tests `CustomResource.get_parameter`
|
||||
# Tests `CustomWorkload.get_parameter`
|
||||
|
||||
parameters = self.custom_workload.get_parameters()
|
||||
self.assertTrue(isinstance(parameters, Dict))
|
||||
@@ -95,7 +95,7 @@ class CustomWorkloadTestSuite(unittest.TestCase):
|
||||
self.assertEquals(6, parameters["arguments"][1])
|
||||
|
||||
def test_add_parameters(self) -> None:
|
||||
# Tests `CustomResource.set_parameter` for the case where we add a new
|
||||
# Tests `CustomWorkload.set_parameter` for the case where we add a new
|
||||
# parameter value.
|
||||
|
||||
self.custom_workload.set_parameter("test_param", 10)
|
||||
@@ -109,7 +109,7 @@ class CustomWorkloadTestSuite(unittest.TestCase):
|
||||
del self.custom_workload.get_parameters()["test_param"]
|
||||
|
||||
def test_override_parameter(self) -> None:
|
||||
# Tests `CustomResource.set_parameter` for the case where we override
|
||||
# Tests `CustomWorkload.set_parameter` for the case where we override
|
||||
# a parameter's value.
|
||||
|
||||
old_value = self.custom_workload.get_parameters()["binary"]
|
||||
|
||||
@@ -21,11 +21,6 @@ services:
|
||||
context: systemc-2.3.3
|
||||
dockerfile: Dockerfile
|
||||
image: gcr.io/gem5-test/systemc-env:latest
|
||||
ubuntu-18.04_all-dependencies:
|
||||
build:
|
||||
context: ubuntu-18.04_all-dependencies
|
||||
dockerfile: Dockerfile
|
||||
image: gcr.io/gem5-test/ubuntu-18.04_all-dependencies:latest
|
||||
ubuntu-20.04_all-dependencies:
|
||||
build:
|
||||
context: ubuntu-20.04_all-dependencies
|
||||
@@ -41,16 +36,9 @@ services:
|
||||
context: ubuntu-22.04_min-dependencies
|
||||
dockerfile: Dockerfile
|
||||
image: gcr.io/gem5-test/ubuntu-22.04_min-dependencies:latest
|
||||
gcc-7:
|
||||
build:
|
||||
context: ubuntu-18.04_gcc-version
|
||||
dockerfile: Dockerfile
|
||||
args:
|
||||
- version=7
|
||||
image: gcr.io/gem5-test/gcc-version-7:latest
|
||||
gcc-8:
|
||||
build:
|
||||
context: ubuntu-18.04_gcc-version
|
||||
context: ubuntu-20.04_gcc-version
|
||||
dockerfile: Dockerfile
|
||||
args:
|
||||
- version=8
|
||||
@@ -83,30 +71,23 @@ services:
|
||||
args:
|
||||
- version=12
|
||||
image: gcr.io/gem5-test/gcc-version-12:latest
|
||||
clang-6:
|
||||
build:
|
||||
context: ubuntu-18.04_clang-version
|
||||
dockerfile: Dockerfile
|
||||
args:
|
||||
- version=6.0
|
||||
image: gcr.io/gem5-test/clang-version-6.0:latest
|
||||
clang-7:
|
||||
build:
|
||||
context: ubuntu-18.04_clang-version
|
||||
context: ubuntu-20.04_clang-version
|
||||
dockerfile: Dockerfile
|
||||
args:
|
||||
- version=7
|
||||
image: gcr.io/gem5-test/clang-version-7:latest
|
||||
clang-8:
|
||||
build:
|
||||
context: ubuntu-18.04_clang-version
|
||||
context: ubuntu-20.04_clang-version
|
||||
dockerfile: Dockerfile
|
||||
args:
|
||||
- version=8
|
||||
image: gcr.io/gem5-test/clang-version-8:latest
|
||||
clang-9:
|
||||
build:
|
||||
context: ubuntu-18.04_clang-version
|
||||
context: ubuntu-20.04_clang-version
|
||||
dockerfile: Dockerfile
|
||||
args:
|
||||
- version=9
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
# Copyright (c) 2020 The Regents of the University of California
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met: redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer;
|
||||
# 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;
|
||||
# neither the name of the copyright holders 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
|
||||
# OWNER 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.
|
||||
|
||||
FROM ubuntu:18.04
|
||||
|
||||
RUN apt -y update && apt -y upgrade && \
|
||||
apt -y install build-essential git m4 scons zlib1g zlib1g-dev \
|
||||
libprotobuf-dev protobuf-compiler libprotoc-dev libgoogle-perftools-dev \
|
||||
python3-dev python3 doxygen libboost-all-dev \
|
||||
libhdf5-serial-dev python3-pydot libpng-dev libelf-dev pkg-config \
|
||||
python3-pip python3-venv
|
||||
|
||||
RUN pip3 install black mypy pre-commit
|
||||
|
||||
RUN update-alternatives --install /usr/bin/python python /usr/bin/python3 10
|
||||
RUN update-alternatives --install /usr/bin/python python /usr/bin/python2 1
|
||||
@@ -1,53 +0,0 @@
|
||||
# Copyright (c) 2020 The Regents of the University of California
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met: redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer;
|
||||
# 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;
|
||||
# neither the name of the copyright holders 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
|
||||
# OWNER 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.
|
||||
|
||||
FROM ubuntu:18.04
|
||||
|
||||
# Valid version values:
|
||||
# 3.9
|
||||
# 4.0
|
||||
# 5.0
|
||||
# 6.0
|
||||
# 7
|
||||
# 8
|
||||
# 9
|
||||
ARG version
|
||||
|
||||
RUN apt -y update && apt -y upgrade && \
|
||||
apt -y install git m4 scons zlib1g zlib1g-dev clang-${version} \
|
||||
libprotobuf-dev protobuf-compiler libprotoc-dev libgoogle-perftools-dev \
|
||||
python3-dev python3 doxygen make
|
||||
|
||||
RUN apt-get --purge -y remove gcc
|
||||
|
||||
RUN update-alternatives --install \
|
||||
/usr/bin/clang++ clang++ /usr/bin/clang++-${version} 100
|
||||
RUN update-alternatives --install \
|
||||
/usr/bin/clang clang /usr/bin/clang-${version} 100
|
||||
RUN update-alternatives --install \
|
||||
/usr/bin/c++ c++ /usr/bin/clang++-${version} 100
|
||||
RUN update-alternatives --install \
|
||||
/usr/bin/cc cc /usr/bin/clang-${version} 100
|
||||
@@ -1,49 +0,0 @@
|
||||
# Copyright (c) 2020 The Regents of the University of California
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met: redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer;
|
||||
# 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;
|
||||
# neither the name of the copyright holders 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
|
||||
# OWNER 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.
|
||||
FROM ubuntu:18.04
|
||||
|
||||
# Valid version values:
|
||||
# 4.8
|
||||
# 5
|
||||
# 6
|
||||
# 7
|
||||
# 8
|
||||
ARG version
|
||||
|
||||
RUN apt -y update && apt -y upgrade && \
|
||||
apt -y install git m4 scons zlib1g zlib1g-dev gcc-multilib \
|
||||
libprotobuf-dev protobuf-compiler libprotoc-dev libgoogle-perftools-dev \
|
||||
python3-dev python3 doxygen wget zip gcc-${version} \
|
||||
g++-${version} make
|
||||
|
||||
RUN update-alternatives --install \
|
||||
/usr/bin/g++ g++ /usr/bin/g++-${version} 100
|
||||
RUN update-alternatives --install \
|
||||
/usr/bin/gcc gcc /usr/bin/gcc-${version} 100
|
||||
RUN update-alternatives --install \
|
||||
/usr/bin/c++ c++ /usr/bin/g++-${version} 100
|
||||
RUN update-alternatives --install \
|
||||
/usr/bin/cc cc /usr/bin/gcc-${version} 100
|
||||
@@ -97,6 +97,20 @@ If you wish to destroy all the VMs you can run:
|
||||
|
||||
**Note:** This script assumes "VAGRANT_HOME" is set to the CWD.
|
||||
|
||||
## Improving stability
|
||||
|
||||
Occasionally GitHub runner services, or VMs, go down. This is often silent and
|
||||
usually only noticable from going to the GitHub repo page "settings" -> "actions" -> "runners" and observing the status.
|
||||
When the VMs or the service stop working they need restarted.
|
||||
To do so you can sun `./vm_manager.sh`. This will cycle through the VMs and execute a `vagrant up` command.
|
||||
This does one of three things depending on the state of the VM:
|
||||
|
||||
1. If the VM is down this will bring the VM back online and start the GitHub runner service.
|
||||
2. If the VM is up but the GitHub runner service is down, this will start the GitHub runner service.
|
||||
3. If the VM is up and the GitHub runner service is running (i.e., everything is fine) then this does nothing.
|
||||
|
||||
Given there is no harm in running this command frequently, we recommend setting up a cron job to automatically execute `./vm_manager.sh` every few hours.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### The default libvirt disk image storage pool is on the wrong drive
|
||||
|
||||
Reference in New Issue
Block a user