Repository navigation
emulator: select the HBM generation and channel count from settings - #119
Shreyas8612 wants to merge 1 commit into
Conversation
The Ramulator model was hard-coded to `hbm2_preset(8)` in runner.rs, so
neither the HBM generation nor the channel count could be changed
without rebuilding, and the ramulator crate had no HBM3 device model.
Add TRANSACTIONAL.CONFIG.HBM_GEN ("hbm2" | "hbm3") and HBM_CHANNELS to
plena_settings.toml with --hbm-gen / --hbm-channels CLI overrides, and
have the runner pick the preset from them. Both keys are optional and
default to hbm2 / 8, so existing settings files and runs are unchanged.
Add `Ramulator::hbm3_preset`, backed by a new config/hbm3.rs that
reproduces ramulator 2.1's data-driven HBM3 spec (JESD238 HBM3_8Gb_8hi
organisation at the 6.4 Gb/s speed bin, half-CK ticks, dual command
bus) exactly as upstream's Python generator serialises it, on the HBM34
controller. Expose the channel count on the model wrapper so presets
can be checked, and document the settings in the emulator readme.
Verified with cargo fmt, cargo clippy --workspace --all-targets
-D warnings and cargo test --workspace: the HBM3 config matches the
upstream generator's output for the same presets, hbm3_preset(16)
builds with 16 channels at a 312 ps tick and 32-byte transfers,
hbm2_preset(8) keeps its shape, and the settings default/override
resolution is pinned. The ATen linear testbench passes on the default
path and produces identical results with --hbm-gen hbm3.
There was a problem hiding this comment.
🟡 Changes recommended
CLI overrides use eager unwrap_or fallbacks, so invalid settings can still panic before the override is applied.
Get a fresh assessment by requesting another Copilot review.
Pull request overview
Adds configurable HBM generation and channel count selection, including a new Ramulator HBM3 model and CLI/settings integration.
Changes:
- Adds
HBM_GENandHBM_CHANNELSsettings with CLI overrides. - Implements and tests the HBM3 Ramulator preset.
- Documents the new configuration options.
File summaries
| File | Description |
|---|---|
transactional_emulator/src/runtime_config.rs |
Exposes HBM settings at runtime. |
transactional_emulator/src/runner.rs |
Resolves settings and selects the Ramulator preset. |
transactional_emulator/src/load_config.rs |
Parses, defaults, and validates HBM settings. |
transactional_emulator/src/cli.rs |
Adds HBM CLI overrides. |
transactional_emulator/readme.md |
Documents HBM configuration. |
transactional_emulator/lib/ramulator/src/raw.rs |
Adds HBM3 controller and transfer metadata. |
transactional_emulator/lib/ramulator/src/preset.rs |
Adds HBM3 and preserves HBM2 presets. |
transactional_emulator/lib/ramulator/src/model.rs |
Exposes channel count. |
transactional_emulator/lib/ramulator/src/config/hbm3.rs |
Defines the HBM3 device specification. |
transactional_emulator/lib/ramulator/src/config.rs |
Registers HBM3 configuration types. |
README.md |
Updates configuration overview. |
plena_settings.toml |
Adds default HBM settings. |
Review details
Suppressed comments (1)
transactional_emulator/src/runner.rs:43
Option::unwrap_oreagerly evaluates*HBM_GEN, so--hbm-gen hbm3still parses the settings value before using the CLI value. An invalidHBM_GENin the settings file will panic instead of being overridden, so use a lazy fallback here as well.
(cli_gen.unwrap_or(*HBM_GEN), channels)
- Files reviewed: 12/12 changed files
- Comments generated: 1
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| /// Resolve the Ramulator HBM geometry: `--hbm-gen` / `--hbm-channels` win | ||
| /// over `HBM_GEN` / `HBM_CHANNELS` from plena_settings.toml. | ||
| fn resolve_hbm_model(cli_gen: Option<HbmGen>, cli_channels: Option<usize>) -> (HbmGen, usize) { | ||
| let channels = cli_channels.unwrap_or(*HBM_CHANNELS); |
There was a problem hiding this comment.
Hmmm, could you clarify why we need a separate config/hbm3.rs instead of using Ramulator 2.1’s upstream HBM3 model/configuration directly?
Also, have you done any cross-validation experiments on your model? We verified the HBM2E model with our V80 FPGA board.
There was a problem hiding this comment.
Why a separate config/hbm3.rs
It is upstream's HBM3 model: the C++ device (src/ramulator/dram/impl/HBM3.cpp) is used unchanged. What the file supplies is the device configuration. Since ramulator 2.1 the C++ devices are generated from Python (HBM3.cpp is marked auto-generated from python/ramulator/dram/hbm3.py) and no longer carry presets: DRAMSpec::load_config reads the organisation counts, timing values, timing-constraint list, read_latency and command_cycles from the config, which upstream normally produces with its Python package. Our pkgs/ramulator2 builds with the Python bindings off and the emulator passes only a config string through the C API, so, like config/hbm2.rs and config/ddr4.rs from #102, the presets and constraint table have to be rendered on our side.
To check it is a faithful port, I generated the config with upstream's own Python at the commit pkgs/ramulator2 pins (b3efdc5), for the same presets (HBM3_8Gb_8hi, HBM3_6400Mbps), and compared it with what hbm3.rs serialises:
| Field | Result |
|---|---|
| organisation (dq, level counts) | identical |
| timing values (29) | identical |
| timing constraints | identical, 52 of 52, same order |
read_latency, channel_width, command_cycles |
identical |
If you'd rather not maintain Rust ports, the alternative is to generate these tables from upstream's Python inside the nix derivation (or check in the generated JSON). Happy to switch to that.
Side note from the same check: as a control I ran the comparison on main's hbm2.rs, and it does not match the pinned upstream generator. Upstream treats ACT as a 2-cycle command, so it adds a 2-cycle command-bus occupancy after ACT and shifts 16 ACT-adjacent constraints by one cycle (e.g. bank ACT→RD 15 vs 14, PRE→ACT 13 vs 14). Since that's the model you validated on the V80 I haven't touched it; just flagging it in case the V80 match was against an earlier ramulator revision.
Cross-validation
No hardware cross-validation: I don't have an HBM3 platform, so this preset isn't validated the way your HBM2E path is. Beyond the spec-level check above, I ran a same-harness sanity check against the HBM2 preset (lib/ramulator, 64 B reads over 64 MiB):
| Preset | Idle 64 B read | Sequential read, 1024 in flight | Of nominal peak |
|---|---|---|---|
hbm2, 8 channels |
34.0 ns | 112.2 GB/s | 87.6% of 128 GB/s |
hbm3, 16 channels |
33.7 ns | 691.3 GB/s | 84.4% of 819.2 GB/s |
So it behaves consistently with the validated preset, but these are JEDEC-spec numbers, not measurements. Three options, your call:
- Keep it, default stays
hbm2, and I label HBM3 "spec-level, not hardware-validated" in the readme, the settings comment and the startup log. - Drop HBM3 from this PR and keep only the
HBM_CHANNELSsetting. - If your V80 harness is in the repo, point me at it and I'll run the identical access pattern on both presets.
The Ramulator model was hard-coded to hbm2_preset(8) in runner.rs, so
neither the HBM generation nor the channel count could be changed
without rebuilding, and the ramulator crate had no HBM3 device model.
Add TRANSACTIONAL.CONFIG.HBM_GEN ("hbm2" | "hbm3") and HBM_CHANNELS to
plena_settings.toml with --hbm-gen / --hbm-channels CLI overrides, and
have the runner pick the preset from them. Both keys are optional and
default to hbm2 / 8, so existing settings files and runs are unchanged.
Add Ramulator::hbm3_preset, backed by a new config/hbm3.rs that
reproduces ramulator 2.1's data-driven HBM3 spec (JESD238 HBM3_8Gb_8hi
organisation at the 6.4 Gb/s speed bin, half-CK ticks, dual command
bus) exactly as upstream's Python generator serialises it, on the HBM34
controller. Expose the channel count on the model wrapper so presets
can be checked, and document the settings in the emulator readme.
Verified with cargo fmt, cargo clippy --workspace --all-targets
-D warnings and cargo test --workspace: the HBM3 config matches the
upstream generator's output for the same presets, hbm3_preset(16)
builds with 16 channels at a 312 ps tick and 32-byte transfers,
hbm2_preset(8) keeps its shape, and the settings default/override
resolution is pinned. The ATen linear testbench passes on the default
path and produces identical results with --hbm-gen hbm3.