Merge branch 'develop' into fix-invalid-pc-on-bubble

This commit is contained in:
Jason Lowe-Power
2023-07-21 08:10:03 -07:00
committed by GitHub
71 changed files with 1366 additions and 571 deletions

62
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View 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.

View File

@@ -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 }}."

View File

@@ -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

View File

@@ -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

View File

@@ -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
View File

@@ -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
View 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.

View 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)}}")

View File

@@ -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.

View File

@@ -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(

View File

@@ -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.

View File

@@ -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.

View File

@@ -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)

View File

@@ -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)

View File

@@ -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)

View File

@@ -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,
)

View File

@@ -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,
)

View File

@@ -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,
)

View File

@@ -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,
)

View File

@@ -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,
)

View 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()

View File

@@ -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"),
)

View File

@@ -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()

View File

@@ -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]}',

View File

@@ -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")

View File

@@ -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);

View File

@@ -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;
}
/**

View File

@@ -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.

View File

@@ -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 &sectionName)
{
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 &sectionName)
{
return const_cast<IniFile::Section*>(
std::as_const(*this).findSection(sectionName));
}
const IniFile::Section *
IniFile::findSection(const std::string &sectionName) 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 &sectionName, 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 &sectionName,
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 &sectionName) const
bool
IniFile::Section::printUnreferenced(const std::string &sectionName)
IniFile::Section::printUnreferenced(const std::string &sectionName) 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 &sectionName)
}
}
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 &sectionName)
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 &sectionName = 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 &sectionName)
IniFile::Section::dump(const std::string &sectionName) 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 &sectionName,
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());
}
}

View File

@@ -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 &sectionName);
bool printUnreferenced(const std::string &sectionName) const;
/// Print the contents of this section to cout (for debugging).
void dump(const std::string &sectionName);
void dump(const std::string &sectionName) 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 &sectionName) const;
Section *findSection(const std::string &sectionName);
const Section *findSection(const std::string &sectionName) 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();

View File

@@ -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();

View File

@@ -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;
}

View File

@@ -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)"

View File

@@ -71,12 +71,15 @@ BaseKvmCPU::BaseKvmCPU(const BaseKvmCPUParams &params)
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 &params)
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;
}

View File

@@ -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?

View File

@@ -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);
}

View File

@@ -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}
}""",
)

View File

@@ -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}
}
""",
)

View File

@@ -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}
}
""",
)

View File

@@ -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}
}
""",
)

View File

@@ -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}
}
""",
)

View File

@@ -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}
}
""",
)

View File

@@ -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;

View File

@@ -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;
}
}

View File

@@ -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) {

View File

@@ -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']:

View File

@@ -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')

View File

@@ -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

View File

@@ -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",
)
```

View File

@@ -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)

View File

@@ -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
View 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}
}
"""

View File

@@ -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()

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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"

View File

@@ -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,
),

View File

@@ -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(

View File

@@ -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.

View File

@@ -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,

View File

@@ -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

View File

@@ -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)

View File

@@ -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)

View File

@@ -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)

View File

@@ -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",

View File

@@ -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"]

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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