bpred 0.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- bpred-0.2.0/.github/workflows/ci.yml +22 -0
- bpred-0.2.0/.gitignore +42 -0
- bpred-0.2.0/CHANGELOG.md +34 -0
- bpred-0.2.0/CLAUDE.md +59 -0
- bpred-0.2.0/CODE_OF_CONDUCT.md +39 -0
- bpred-0.2.0/CONTRIBUTING.md +45 -0
- bpred-0.2.0/LICENSE +21 -0
- bpred-0.2.0/PKG-INFO +172 -0
- bpred-0.2.0/README.md +122 -0
- bpred-0.2.0/SECURITY.md +22 -0
- bpred-0.2.0/assets/logo.png +0 -0
- bpred-0.2.0/docs/architecture.md +101 -0
- bpred-0.2.0/docs/charter.md +45 -0
- bpred-0.2.0/docs/logo-prompt.md +7 -0
- bpred-0.2.0/examples/README.md +45 -0
- bpred-0.2.0/examples/sample.trace +28 -0
- bpred-0.2.0/pyproject.toml +55 -0
- bpred-0.2.0/src/bpred/__init__.py +42 -0
- bpred-0.2.0/src/bpred/bimodal.py +70 -0
- bpred-0.2.0/src/bpred/cli.py +167 -0
- bpred-0.2.0/src/bpred/counter.py +70 -0
- bpred-0.2.0/src/bpred/gshare.py +94 -0
- bpred-0.2.0/src/bpred/perceptron.py +183 -0
- bpred-0.2.0/src/bpred/py.typed +0 -0
- bpred-0.2.0/src/bpred/tournament.py +137 -0
- bpred-0.2.0/src/bpred/trace.py +95 -0
- bpred-0.2.0/tests/__init__.py +0 -0
- bpred-0.2.0/tests/test_bimodal.py +90 -0
- bpred-0.2.0/tests/test_counter.py +113 -0
- bpred-0.2.0/tests/test_gshare.py +105 -0
- bpred-0.2.0/tests/test_perceptron.py +332 -0
- bpred-0.2.0/tests/test_property.py +114 -0
- bpred-0.2.0/tests/test_tournament.py +135 -0
- bpred-0.2.0/tests/test_trace.py +120 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
test:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
strategy:
|
|
12
|
+
matrix:
|
|
13
|
+
python: ["3.10", "3.11", "3.12", "3.13"]
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v4
|
|
16
|
+
- uses: actions/setup-python@v5
|
|
17
|
+
with:
|
|
18
|
+
python-version: ${{ matrix.python }}
|
|
19
|
+
- run: pip install -e ".[dev]"
|
|
20
|
+
- run: ruff check .
|
|
21
|
+
- run: mypy src
|
|
22
|
+
- run: pytest -q
|
bpred-0.2.0/.gitignore
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*.pyo
|
|
5
|
+
*.pyd
|
|
6
|
+
*.so
|
|
7
|
+
*.egg
|
|
8
|
+
*.egg-info/
|
|
9
|
+
dist/
|
|
10
|
+
build/
|
|
11
|
+
.eggs/
|
|
12
|
+
.cache/
|
|
13
|
+
.mypy_cache/
|
|
14
|
+
.ruff_cache/
|
|
15
|
+
.pytest_cache/
|
|
16
|
+
htmlcov/
|
|
17
|
+
.coverage
|
|
18
|
+
coverage.xml
|
|
19
|
+
|
|
20
|
+
# Virtual environments
|
|
21
|
+
.venv/
|
|
22
|
+
venv/
|
|
23
|
+
env/
|
|
24
|
+
ENV/
|
|
25
|
+
|
|
26
|
+
# uv
|
|
27
|
+
uv.lock
|
|
28
|
+
|
|
29
|
+
# Distribution / packaging
|
|
30
|
+
*.tar.gz
|
|
31
|
+
*.whl
|
|
32
|
+
MANIFEST
|
|
33
|
+
|
|
34
|
+
# IDEs
|
|
35
|
+
.idea/
|
|
36
|
+
.vscode/
|
|
37
|
+
*.swp
|
|
38
|
+
*.swo
|
|
39
|
+
*~
|
|
40
|
+
|
|
41
|
+
# macOS
|
|
42
|
+
.DS_Store
|
bpred-0.2.0/CHANGELOG.md
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
6
|
+
This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [0.2.0] - 2026-06-17
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- `PerceptronPredictor`: Jimenez and Lin (2001) table of integer-weight perceptrons.
|
|
13
|
+
Captures linearly-separable history patterns that bimodal and gshare cannot learn.
|
|
14
|
+
Constructor: `PerceptronPredictor(history_length=H, table_size=N)`.
|
|
15
|
+
Exported from `bpred` top-level package.
|
|
16
|
+
|
|
17
|
+
### Notes
|
|
18
|
+
|
|
19
|
+
- PyPI publish is queued behind the new-project creation quota (currently
|
|
20
|
+
rate-limited). Build artifact passes `twine check`. Publish will follow once
|
|
21
|
+
the quota resets.
|
|
22
|
+
|
|
23
|
+
## [0.1.0] - 2026-06-17
|
|
24
|
+
|
|
25
|
+
### Added
|
|
26
|
+
|
|
27
|
+
- `SaturatingCounter`: n-bit saturating counter building block.
|
|
28
|
+
- `BimodalPredictor`: Smith (1981) table of saturating counters indexed by PC.
|
|
29
|
+
- `GsharePredictor`: McFarling (1993) global-history XOR predictor.
|
|
30
|
+
- `TournamentPredictor`: McFarling (1993) / Alpha 21264-style meta-selecting predictor.
|
|
31
|
+
- `run_trace`, `accuracy`, `mispredictions`: trace-driven simulation utilities.
|
|
32
|
+
- `bpred` CLI supporting bimodal, gshare, and tournament subcommands.
|
|
33
|
+
- Full mypy strict and ruff linting.
|
|
34
|
+
- CI on Python 3.10, 3.11, 3.12, 3.13.
|
bpred-0.2.0/CLAUDE.md
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# bpred -- Project Instructions
|
|
2
|
+
|
|
3
|
+
## What this is
|
|
4
|
+
|
|
5
|
+
Pure-Python simulator of classical CPU branch predictors (bimodal, gshare,
|
|
6
|
+
tournament). Zero runtime dependencies. Target: Python 3.10+.
|
|
7
|
+
|
|
8
|
+
## Source layout
|
|
9
|
+
|
|
10
|
+
```
|
|
11
|
+
src/bpred/
|
|
12
|
+
counter.py -- SaturatingCounter (shared building block)
|
|
13
|
+
bimodal.py -- BimodalPredictor
|
|
14
|
+
gshare.py -- GsharePredictor
|
|
15
|
+
tournament.py -- TournamentPredictor + BranchPredictor protocol
|
|
16
|
+
trace.py -- run_trace, accuracy, mispredictions, TraceResult
|
|
17
|
+
cli.py -- argparse CLI entry point
|
|
18
|
+
__init__.py -- public re-exports
|
|
19
|
+
py.typed -- PEP 561 marker
|
|
20
|
+
tests/
|
|
21
|
+
test_counter.py -- golden FSM values + property tests for counter
|
|
22
|
+
test_bimodal.py
|
|
23
|
+
test_gshare.py
|
|
24
|
+
test_tournament.py
|
|
25
|
+
test_property.py -- property-style exhaustive tests
|
|
26
|
+
test_trace.py
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Conventions
|
|
30
|
+
|
|
31
|
+
- No default parameter values anywhere. All parameters are keyword-only.
|
|
32
|
+
- Strict mypy passes on all files in src/.
|
|
33
|
+
- ruff lint set: E, F, I, UP, ANN.
|
|
34
|
+
- No runtime dependencies (stdlib only).
|
|
35
|
+
- No em dash characters in any file.
|
|
36
|
+
- Commits: `type(scope): description`. No Co-authored-by trailers.
|
|
37
|
+
|
|
38
|
+
## Running checks
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
pytest -q
|
|
42
|
+
ruff check .
|
|
43
|
+
mypy src
|
|
44
|
+
uv build
|
|
45
|
+
uv run --with twine twine check dist/*
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Predictor invariants
|
|
49
|
+
|
|
50
|
+
- SaturatingCounter value always stays in [0, max_value].
|
|
51
|
+
- predict() is a pure function of current state.
|
|
52
|
+
- Gshare GHR is updated AFTER recording the prediction.
|
|
53
|
+
- Tournament: chooser updated only when sub-predictors disagree.
|
|
54
|
+
- Tournament: both sub-predictors always updated regardless of chooser.
|
|
55
|
+
|
|
56
|
+
## What NOT to assert in tests
|
|
57
|
+
|
|
58
|
+
Do NOT assert that tournament is never worse than both sub-predictors on a
|
|
59
|
+
single prediction. A meta-selector can choose the wrong sub-predictor.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Code of Conduct
|
|
2
|
+
|
|
3
|
+
## Our Pledge
|
|
4
|
+
|
|
5
|
+
We as contributors and maintainers pledge to make participation in this project
|
|
6
|
+
a harassment-free experience for everyone, regardless of age, body size,
|
|
7
|
+
disability, ethnicity, sex characteristics, gender identity and expression,
|
|
8
|
+
level of experience, education, socioeconomic status, nationality, personal
|
|
9
|
+
appearance, race, religion, or sexual identity and orientation.
|
|
10
|
+
|
|
11
|
+
## Our Standards
|
|
12
|
+
|
|
13
|
+
Examples of behaviour that contributes to a positive environment:
|
|
14
|
+
|
|
15
|
+
- Using welcoming and inclusive language.
|
|
16
|
+
- Being respectful of differing viewpoints and experiences.
|
|
17
|
+
- Gracefully accepting constructive criticism.
|
|
18
|
+
- Focusing on what is best for the community.
|
|
19
|
+
- Showing empathy toward other community members.
|
|
20
|
+
|
|
21
|
+
Examples of unacceptable behaviour:
|
|
22
|
+
|
|
23
|
+
- The use of sexualised language or imagery.
|
|
24
|
+
- Trolling, insulting or derogatory comments, and personal or political attacks.
|
|
25
|
+
- Public or private harassment.
|
|
26
|
+
- Publishing others' private information without explicit permission.
|
|
27
|
+
- Other conduct which could reasonably be considered inappropriate in a
|
|
28
|
+
professional setting.
|
|
29
|
+
|
|
30
|
+
## Enforcement
|
|
31
|
+
|
|
32
|
+
Instances of abusive, harassing, or otherwise unacceptable behaviour may be
|
|
33
|
+
reported by opening a GitHub issue or contacting the maintainer directly.
|
|
34
|
+
All complaints will be reviewed and investigated promptly and fairly.
|
|
35
|
+
|
|
36
|
+
## Attribution
|
|
37
|
+
|
|
38
|
+
This Code of Conduct is adapted from the
|
|
39
|
+
[Contributor Covenant](https://www.contributor-covenant.org), version 2.1.
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
Thank you for your interest in contributing to `bpred`.
|
|
4
|
+
|
|
5
|
+
## Setup
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
git clone https://github.com/amaar-mc/bpred
|
|
9
|
+
cd bpred
|
|
10
|
+
pip install -e ".[dev]"
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Running checks
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
pytest -q # tests
|
|
17
|
+
ruff check . # linting
|
|
18
|
+
mypy src # type checking
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
All three must pass before opening a pull request.
|
|
22
|
+
|
|
23
|
+
## Guidelines
|
|
24
|
+
|
|
25
|
+
- Zero runtime dependencies. All new code must work with the Python standard
|
|
26
|
+
library only.
|
|
27
|
+
- Strict typing. All public functions must have complete type annotations, and
|
|
28
|
+
`mypy --strict` must pass.
|
|
29
|
+
- No default parameter values on public APIs. All parameters must be explicit
|
|
30
|
+
keyword arguments.
|
|
31
|
+
- Test behaviour, not implementation. New predictors must come with tests
|
|
32
|
+
covering correctness on structured traces, not just "it ran without crashing."
|
|
33
|
+
- Bug fixes: add a failing test first, then fix the bug.
|
|
34
|
+
|
|
35
|
+
## Pull requests
|
|
36
|
+
|
|
37
|
+
- Open an issue first for significant changes.
|
|
38
|
+
- Keep commits focused. One logical change per commit.
|
|
39
|
+
- Commit message format: `type(scope): description` (e.g.
|
|
40
|
+
`feat(gshare): add history_bits validation`).
|
|
41
|
+
- Do not add `Co-authored-by` trailers or automated tool footers.
|
|
42
|
+
|
|
43
|
+
## Code of Conduct
|
|
44
|
+
|
|
45
|
+
See [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md).
|
bpred-0.2.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Amaar Chughtai
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
bpred-0.2.0/PKG-INFO
ADDED
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: bpred
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Pure-Python simulator of classical CPU branch predictors: bimodal, gshare, and tournament
|
|
5
|
+
Project-URL: Homepage, https://github.com/amaar-mc/bpred
|
|
6
|
+
Project-URL: Repository, https://github.com/amaar-mc/bpred
|
|
7
|
+
Project-URL: Issues, https://github.com/amaar-mc/bpred/issues
|
|
8
|
+
Author-email: Amaar Chughtai <amaardevx@gmail.com>
|
|
9
|
+
License: MIT License
|
|
10
|
+
|
|
11
|
+
Copyright (c) 2026 Amaar Chughtai
|
|
12
|
+
|
|
13
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
14
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
15
|
+
in the Software without restriction, including without limitation the rights
|
|
16
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
17
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
18
|
+
furnished to do so, subject to the following conditions:
|
|
19
|
+
|
|
20
|
+
The above copyright notice and this permission notice shall be included in all
|
|
21
|
+
copies or substantial portions of the Software.
|
|
22
|
+
|
|
23
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
24
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
25
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
26
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
27
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
28
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
29
|
+
SOFTWARE.
|
|
30
|
+
License-File: LICENSE
|
|
31
|
+
Keywords: bimodal,branch-prediction,computer-architecture,cpu-simulator,education,gshare
|
|
32
|
+
Classifier: Development Status :: 3 - Alpha
|
|
33
|
+
Classifier: Intended Audience :: Education
|
|
34
|
+
Classifier: Intended Audience :: Science/Research
|
|
35
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
36
|
+
Classifier: Programming Language :: Python :: 3
|
|
37
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
38
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
39
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
40
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
41
|
+
Classifier: Topic :: Education
|
|
42
|
+
Classifier: Topic :: Scientific/Engineering
|
|
43
|
+
Classifier: Typing :: Typed
|
|
44
|
+
Requires-Python: >=3.10
|
|
45
|
+
Provides-Extra: dev
|
|
46
|
+
Requires-Dist: mypy>=1.10; extra == 'dev'
|
|
47
|
+
Requires-Dist: pytest>=8; extra == 'dev'
|
|
48
|
+
Requires-Dist: ruff>=0.4; extra == 'dev'
|
|
49
|
+
Description-Content-Type: text/markdown
|
|
50
|
+
|
|
51
|
+
# bpred
|
|
52
|
+
|
|
53
|
+
<p align="center">
|
|
54
|
+
<img src="assets/logo.png" alt="bpred logo" width="160">
|
|
55
|
+
</p>
|
|
56
|
+
|
|
57
|
+
Pure-Python simulator of classical CPU branch predictors for computer architecture education.
|
|
58
|
+
|
|
59
|
+
Implements four predictors from first principles with zero runtime dependencies:
|
|
60
|
+
|
|
61
|
+
- **Bimodal** (Smith 1981) -- a table of n-bit saturating counters indexed by PC.
|
|
62
|
+
- **Gshare** (McFarling 1993) -- PC XOR global-history register indexes 2-bit counters.
|
|
63
|
+
- **Tournament** (McFarling 1993 / Alpha 21264) -- a meta-selector combining local and global sub-predictors.
|
|
64
|
+
- **Perceptron** (Jimenez and Lin 2001) -- a table of integer-weight perceptrons that can learn linearly-separable history patterns bimodal and gshare cannot capture.
|
|
65
|
+
|
|
66
|
+
Part of the same open-source computer architecture education series as [tomasulo](https://github.com/amaar-mc/tomasulo) (out-of-order execution) and scoreboarding.
|
|
67
|
+
|
|
68
|
+
## Install
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
pip install bpred
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
PyPI publication is pending; install from source in the meantime:
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
git clone https://github.com/amaar-mc/bpred
|
|
78
|
+
cd bpred
|
|
79
|
+
pip install -e ".[dev]"
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Python API
|
|
83
|
+
|
|
84
|
+
```python
|
|
85
|
+
from bpred import BimodalPredictor, GsharePredictor, PerceptronPredictor, TournamentPredictor
|
|
86
|
+
from bpred import run_trace, accuracy, mispredictions
|
|
87
|
+
|
|
88
|
+
# Bimodal: 2-bit counters, 1024-entry table
|
|
89
|
+
pred = BimodalPredictor(counter_bits=2, table_size=1024)
|
|
90
|
+
|
|
91
|
+
# Gshare: 10-bit history, 1024-entry table
|
|
92
|
+
pred = GsharePredictor(history_bits=10, table_size=1024)
|
|
93
|
+
|
|
94
|
+
# Tournament
|
|
95
|
+
from bpred import BimodalPredictor, GsharePredictor
|
|
96
|
+
local = BimodalPredictor(counter_bits=2, table_size=1024)
|
|
97
|
+
global_ = GsharePredictor(history_bits=10, table_size=1024)
|
|
98
|
+
pred = TournamentPredictor(local=local, global_=global_, meta_bits=2)
|
|
99
|
+
|
|
100
|
+
# Perceptron: 12-bit history, 1024-entry table
|
|
101
|
+
pred = PerceptronPredictor(history_length=12, table_size=1024)
|
|
102
|
+
|
|
103
|
+
# Feed a trace
|
|
104
|
+
trace = [(0x1000, True), (0x1004, False), (0x1008, True)]
|
|
105
|
+
result = run_trace(pred, trace=trace)
|
|
106
|
+
print(accuracy(trace_result=result)) # e.g. 0.6667
|
|
107
|
+
print(mispredictions(trace_result=result)) # e.g. 1
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### Why use the perceptron predictor?
|
|
111
|
+
|
|
112
|
+
Bimodal and gshare each use a single scalar counter per table entry, so they
|
|
113
|
+
can only learn the *average* bias of a branch. When the taken/not-taken
|
|
114
|
+
outcome correlates with a specific combination of recent history bits (a
|
|
115
|
+
linearly-separable pattern), those predictors plateau.
|
|
116
|
+
|
|
117
|
+
The perceptron predictor maintains a weight vector per entry. The dot product
|
|
118
|
+
of those weights with the history vector expresses arbitrary linear functions
|
|
119
|
+
over H history bits. This lets it learn, for example, "taken when the last
|
|
120
|
+
4 branches were all taken" or "taken on every other iteration" -- patterns
|
|
121
|
+
that require tracking distinct history bits simultaneously. The trade-off is
|
|
122
|
+
that the predictor needs more warm-up branches to converge and the weights
|
|
123
|
+
grow without bound (in simulation; hardware clamps them to a fixed-point
|
|
124
|
+
range).
|
|
125
|
+
|
|
126
|
+
## CLI
|
|
127
|
+
|
|
128
|
+
```
|
|
129
|
+
bpred bimodal --counter-bits 2 --table-size 1024 path/to/trace.trace
|
|
130
|
+
bpred gshare --history-bits 10 --table-size 1024 path/to/trace.trace
|
|
131
|
+
bpred tournament \
|
|
132
|
+
--local-predictor bimodal --local-counter-bits 2 --local-table-size 1024 \
|
|
133
|
+
--global-predictor gshare --global-history-bits 10 --global-table-size 1024 \
|
|
134
|
+
--meta-bits 2 \
|
|
135
|
+
path/to/trace.trace
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
Trace file format -- one branch per line:
|
|
139
|
+
|
|
140
|
+
```
|
|
141
|
+
# pc taken
|
|
142
|
+
0x1000 1
|
|
143
|
+
0x1004 0
|
|
144
|
+
0x1008 T
|
|
145
|
+
0x100c false
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## Accuracy example
|
|
149
|
+
|
|
150
|
+
Running the bundled sample trace with a gshare predictor:
|
|
151
|
+
|
|
152
|
+
```
|
|
153
|
+
$ bpred gshare --history-bits 4 --table-size 16 examples/sample.trace
|
|
154
|
+
Predictor : GsharePredictor(history_bits=4, table_size=16)
|
|
155
|
+
Branches : 20
|
|
156
|
+
Hits : 18
|
|
157
|
+
Misses : 2
|
|
158
|
+
Accuracy : 90.0000%
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
## Development
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
pip install -e ".[dev]"
|
|
165
|
+
pytest -q
|
|
166
|
+
ruff check .
|
|
167
|
+
mypy src
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
## License
|
|
171
|
+
|
|
172
|
+
MIT. See [LICENSE](LICENSE).
|
bpred-0.2.0/README.md
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# bpred
|
|
2
|
+
|
|
3
|
+
<p align="center">
|
|
4
|
+
<img src="assets/logo.png" alt="bpred logo" width="160">
|
|
5
|
+
</p>
|
|
6
|
+
|
|
7
|
+
Pure-Python simulator of classical CPU branch predictors for computer architecture education.
|
|
8
|
+
|
|
9
|
+
Implements four predictors from first principles with zero runtime dependencies:
|
|
10
|
+
|
|
11
|
+
- **Bimodal** (Smith 1981) -- a table of n-bit saturating counters indexed by PC.
|
|
12
|
+
- **Gshare** (McFarling 1993) -- PC XOR global-history register indexes 2-bit counters.
|
|
13
|
+
- **Tournament** (McFarling 1993 / Alpha 21264) -- a meta-selector combining local and global sub-predictors.
|
|
14
|
+
- **Perceptron** (Jimenez and Lin 2001) -- a table of integer-weight perceptrons that can learn linearly-separable history patterns bimodal and gshare cannot capture.
|
|
15
|
+
|
|
16
|
+
Part of the same open-source computer architecture education series as [tomasulo](https://github.com/amaar-mc/tomasulo) (out-of-order execution) and scoreboarding.
|
|
17
|
+
|
|
18
|
+
## Install
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
pip install bpred
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
PyPI publication is pending; install from source in the meantime:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
git clone https://github.com/amaar-mc/bpred
|
|
28
|
+
cd bpred
|
|
29
|
+
pip install -e ".[dev]"
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Python API
|
|
33
|
+
|
|
34
|
+
```python
|
|
35
|
+
from bpred import BimodalPredictor, GsharePredictor, PerceptronPredictor, TournamentPredictor
|
|
36
|
+
from bpred import run_trace, accuracy, mispredictions
|
|
37
|
+
|
|
38
|
+
# Bimodal: 2-bit counters, 1024-entry table
|
|
39
|
+
pred = BimodalPredictor(counter_bits=2, table_size=1024)
|
|
40
|
+
|
|
41
|
+
# Gshare: 10-bit history, 1024-entry table
|
|
42
|
+
pred = GsharePredictor(history_bits=10, table_size=1024)
|
|
43
|
+
|
|
44
|
+
# Tournament
|
|
45
|
+
from bpred import BimodalPredictor, GsharePredictor
|
|
46
|
+
local = BimodalPredictor(counter_bits=2, table_size=1024)
|
|
47
|
+
global_ = GsharePredictor(history_bits=10, table_size=1024)
|
|
48
|
+
pred = TournamentPredictor(local=local, global_=global_, meta_bits=2)
|
|
49
|
+
|
|
50
|
+
# Perceptron: 12-bit history, 1024-entry table
|
|
51
|
+
pred = PerceptronPredictor(history_length=12, table_size=1024)
|
|
52
|
+
|
|
53
|
+
# Feed a trace
|
|
54
|
+
trace = [(0x1000, True), (0x1004, False), (0x1008, True)]
|
|
55
|
+
result = run_trace(pred, trace=trace)
|
|
56
|
+
print(accuracy(trace_result=result)) # e.g. 0.6667
|
|
57
|
+
print(mispredictions(trace_result=result)) # e.g. 1
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Why use the perceptron predictor?
|
|
61
|
+
|
|
62
|
+
Bimodal and gshare each use a single scalar counter per table entry, so they
|
|
63
|
+
can only learn the *average* bias of a branch. When the taken/not-taken
|
|
64
|
+
outcome correlates with a specific combination of recent history bits (a
|
|
65
|
+
linearly-separable pattern), those predictors plateau.
|
|
66
|
+
|
|
67
|
+
The perceptron predictor maintains a weight vector per entry. The dot product
|
|
68
|
+
of those weights with the history vector expresses arbitrary linear functions
|
|
69
|
+
over H history bits. This lets it learn, for example, "taken when the last
|
|
70
|
+
4 branches were all taken" or "taken on every other iteration" -- patterns
|
|
71
|
+
that require tracking distinct history bits simultaneously. The trade-off is
|
|
72
|
+
that the predictor needs more warm-up branches to converge and the weights
|
|
73
|
+
grow without bound (in simulation; hardware clamps them to a fixed-point
|
|
74
|
+
range).
|
|
75
|
+
|
|
76
|
+
## CLI
|
|
77
|
+
|
|
78
|
+
```
|
|
79
|
+
bpred bimodal --counter-bits 2 --table-size 1024 path/to/trace.trace
|
|
80
|
+
bpred gshare --history-bits 10 --table-size 1024 path/to/trace.trace
|
|
81
|
+
bpred tournament \
|
|
82
|
+
--local-predictor bimodal --local-counter-bits 2 --local-table-size 1024 \
|
|
83
|
+
--global-predictor gshare --global-history-bits 10 --global-table-size 1024 \
|
|
84
|
+
--meta-bits 2 \
|
|
85
|
+
path/to/trace.trace
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Trace file format -- one branch per line:
|
|
89
|
+
|
|
90
|
+
```
|
|
91
|
+
# pc taken
|
|
92
|
+
0x1000 1
|
|
93
|
+
0x1004 0
|
|
94
|
+
0x1008 T
|
|
95
|
+
0x100c false
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## Accuracy example
|
|
99
|
+
|
|
100
|
+
Running the bundled sample trace with a gshare predictor:
|
|
101
|
+
|
|
102
|
+
```
|
|
103
|
+
$ bpred gshare --history-bits 4 --table-size 16 examples/sample.trace
|
|
104
|
+
Predictor : GsharePredictor(history_bits=4, table_size=16)
|
|
105
|
+
Branches : 20
|
|
106
|
+
Hits : 18
|
|
107
|
+
Misses : 2
|
|
108
|
+
Accuracy : 90.0000%
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## Development
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
pip install -e ".[dev]"
|
|
115
|
+
pytest -q
|
|
116
|
+
ruff check .
|
|
117
|
+
mypy src
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## License
|
|
121
|
+
|
|
122
|
+
MIT. See [LICENSE](LICENSE).
|
bpred-0.2.0/SECURITY.md
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Security Policy
|
|
2
|
+
|
|
3
|
+
## Supported Versions
|
|
4
|
+
|
|
5
|
+
| Version | Supported |
|
|
6
|
+
|---------|-----------|
|
|
7
|
+
| 0.1.x | Yes |
|
|
8
|
+
|
|
9
|
+
## Reporting a Vulnerability
|
|
10
|
+
|
|
11
|
+
`bpred` is a pure-Python educational simulator with zero runtime dependencies
|
|
12
|
+
and no network access, secrets handling, or persistent storage. The attack
|
|
13
|
+
surface is minimal.
|
|
14
|
+
|
|
15
|
+
If you discover a security vulnerability (for example, a path traversal issue
|
|
16
|
+
in the CLI trace-file parser), please report it by opening a GitHub issue
|
|
17
|
+
marked with the `security` label. For sensitive matters that should not be
|
|
18
|
+
public, contact the maintainer directly via the email address listed in
|
|
19
|
+
`pyproject.toml`.
|
|
20
|
+
|
|
21
|
+
We aim to acknowledge reports within 72 hours and to release a fix within
|
|
22
|
+
14 days for confirmed vulnerabilities.
|
|
Binary file
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# Predictor Architecture
|
|
2
|
+
|
|
3
|
+
This document describes the three branch predictors implemented in `bpred`,
|
|
4
|
+
their algorithmic basis, and the primary academic references.
|
|
5
|
+
|
|
6
|
+
## References
|
|
7
|
+
|
|
8
|
+
- J. E. Smith, "A study of branch prediction strategies," in _Proceedings of
|
|
9
|
+
the 8th Annual Symposium on Computer Architecture (ISCA)_, pp. 135-148, 1981.
|
|
10
|
+
- S. McFarling, "Combining Branch Predictors," WRL Technical Note TN-36,
|
|
11
|
+
Digital Equipment Corporation Western Research Laboratory, June 1993.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Saturating Counter
|
|
16
|
+
|
|
17
|
+
A saturating counter is the base component of all three predictors. An n-bit
|
|
18
|
+
counter holds a value in [0, 2^n - 1]. It predicts _taken_ when the value is
|
|
19
|
+
>= 2^(n-1) and _not-taken_ otherwise. Taken outcomes increment the counter
|
|
20
|
+
toward the maximum; not-taken outcomes decrement it toward zero. At either
|
|
21
|
+
extreme the counter saturates rather than wrapping.
|
|
22
|
+
|
|
23
|
+
The 2-bit variant (n=2) is the classic design from Smith (1981). Its four
|
|
24
|
+
states are:
|
|
25
|
+
|
|
26
|
+
| Value | Name | Predict |
|
|
27
|
+
|-------|-----------------|---------|
|
|
28
|
+
| 0 | Strongly Not-Taken (SN) | not-taken |
|
|
29
|
+
| 1 | Weakly Not-Taken (WN) | not-taken |
|
|
30
|
+
| 2 | Weakly Taken (WT) | taken |
|
|
31
|
+
| 3 | Strongly Taken (ST) | taken |
|
|
32
|
+
|
|
33
|
+
Two consecutive mispredictions are required to flip the prediction, providing
|
|
34
|
+
hysteresis against noise.
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## Bimodal Predictor
|
|
39
|
+
|
|
40
|
+
**Reference:** Smith (1981).
|
|
41
|
+
|
|
42
|
+
A flat table of `table_size` saturating counters of `counter_bits` bits each.
|
|
43
|
+
The table is indexed by `pc mod table_size`. On every branch:
|
|
44
|
+
|
|
45
|
+
1. Predict using the counter at index `pc mod table_size`.
|
|
46
|
+
2. Update that counter with the actual outcome.
|
|
47
|
+
|
|
48
|
+
Multiple branches whose PCs map to the same entry share a counter (aliasing).
|
|
49
|
+
Larger tables reduce aliasing at the cost of hardware area.
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## Gshare Predictor
|
|
54
|
+
|
|
55
|
+
**Reference:** McFarling (1993).
|
|
56
|
+
|
|
57
|
+
Gshare extends the bimodal idea by incorporating global correlation. A global
|
|
58
|
+
history register (GHR) of `history_bits` bits records the outcomes of the most
|
|
59
|
+
recent branches across the entire program. The table index is:
|
|
60
|
+
|
|
61
|
+
```
|
|
62
|
+
index = (pc XOR ghr) mod table_size
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Each entry is a 2-bit saturating counter. After every branch the actual
|
|
66
|
+
outcome is shifted into the GHR (MSB first), discarding outcomes older than
|
|
67
|
+
`history_bits`.
|
|
68
|
+
|
|
69
|
+
XOR hashing distributes entries more uniformly across the table than either
|
|
70
|
+
PC or GHR alone, and exploits cross-branch correlation to improve accuracy
|
|
71
|
+
on correlated loops and function-call patterns.
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## Tournament Predictor
|
|
76
|
+
|
|
77
|
+
**Reference:** McFarling (1993); Alpha 21264 implementation.
|
|
78
|
+
|
|
79
|
+
A tournament predictor combines two sub-predictors (a local and a global) using
|
|
80
|
+
a meta-selector table. The meta-selector contains saturating counters of
|
|
81
|
+
`meta_bits` bits that choose which sub-predictor to trust for each PC.
|
|
82
|
+
|
|
83
|
+
### Prediction
|
|
84
|
+
|
|
85
|
+
1. Look up the chooser counter at `pc mod chooser_size`.
|
|
86
|
+
2. If counter value < threshold (2^(meta_bits - 1)), use the _local_ predictor.
|
|
87
|
+
3. Otherwise use the _global_ predictor.
|
|
88
|
+
|
|
89
|
+
### Update (Alpha 21264 scheme)
|
|
90
|
+
|
|
91
|
+
Both sub-predictors are always updated with the actual outcome. The chooser is
|
|
92
|
+
updated only when the two sub-predictors _disagree_:
|
|
93
|
+
|
|
94
|
+
- If only the local predictor was correct: decrement the chooser (bias toward local).
|
|
95
|
+
- If only the global predictor was correct: increment the chooser (bias toward global).
|
|
96
|
+
- If both or neither was correct: no chooser update.
|
|
97
|
+
|
|
98
|
+
This approach concentrates meta-selector learning signal on cases where the
|
|
99
|
+
choice actually matters.
|
|
100
|
+
|
|
101
|
+
The chooser table size equals `max(local.table_size, global_.table_size)`.
|