Skip to content

Add support for per-hart start PCs (--pcs)#2199

Open
nabudahab wants to merge 23 commits intoriscv-software-src:masterfrom
nabudahab:master
Open

Add support for per-hart start PCs (--pcs)#2199
nabudahab wants to merge 23 commits intoriscv-software-src:masterfrom
nabudahab:master

Conversation

@nabudahab
Copy link

@nabudahab nabudahab commented Dec 30, 2025

Summary

This PR introduces a new command-line argument --pc-harts to allow specifying different start addresses (PCs) for different harts. This feature is particularly valuable for RTL co-simulation workflows, where the simulator must exactly match the behavior of the RTL design. In these scenarios, the Boot ROM is often bypassed or disabled, and each hart is released from reset at a specific entry point defined by the hardware configuration.

Problem

Currently, Spike defaults to setting the PC for all harts to the ELF entry point or the address specified by --pc.

However, in many bare-metal verification environments and Asymmetric Multi-Processing (AMP) configurations, harts often have distinct reset vectors. For example, a dual-core system might require:

  • Hart 0 to fetch from 0x2000
  • Hart 1 to fetch from 0x4000

Achieving this previously required modifying the C++ source code or relying on a complex bootloader/bootrom to diverge the harts.

Solution

I have added the --pc-harts flag which parses a comma-separated list of HartID:Address pairs.

Usage Example:
spike -p2 --pc-harts=0:0x0,1:0x200 my_program.elf

Implementation Details

  • Added argument parsing for --pc-harts in spike_main/spike.cc.
  • Logic applies the PC overrides to the respective processor_t states after simulation initialization but before the run loop begins.

Testing

Verified using a dual-core bare-metal assembly test (with the boot ROM disabled) where Hart 0 and Hart 1 must execute distinct code sections located at 0x0 and 0x200 respectively. Confirmed that both harts start at the correct overridden addresses.

nabudahab and others added 4 commits December 30, 2025 09:27
Currently, the --pc flag sets the entry point for all processors globally,
or relies on the ELF entry point. This is insufficient for asymmetric
multi-processing (AMP) setups or bare-metal RTL verification where
different harts must begin execution at distinct physical addresses
(e.g., Hart 0 at 0x2000, Hart 1 at 0x4000).

This patch adds the --pc-harts=<H:A,...> argument, allowing users to
explicitly override the start PC for specific hart IDs.
@nabudahab
Copy link
Author

Hello, can someone please review the code so that the CI checks can run? Thanks. I'm always happy to address feedback.

Copy link
Collaborator

@aswaterman aswaterman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can I get a second review from someone else, perhaps @jerryz123?

@nabudahab
Copy link
Author

nabudahab commented Jan 20, 2026

@jerryz123 Gentle nudge as it's been a week since the last update. Let me know if you have any thoughts on the implementation or if there's anything you'd like me to address.

@nabudahab nabudahab changed the title Add support for per-hart start PCs (--pc-harts) Add support for per-hart start PCs (--pcs) Jan 26, 2026
@nabudahab
Copy link
Author

@aswaterman I realized I hadn’t actually applied the spacing/style suggestions earlier — that’s fixed now and pushed. Could you take another quick look / re-approve when you get a chance?

@jerryz123 (or any maintainer) GitHub Actions for this PR is still awaiting maintainer approval to run CI. Could someone approve the workflow runs so checks can execute? Once CI is green, this should be ready to merge.

Copy link
Collaborator

@jerryz123 jerryz123 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whoops, sorry. Need to fix my github notification filtering.

nabudahab and others added 9 commits January 26, 2026 23:51
Co-authored-by: Jerry Zhao <qwertyuiopghb@gmail.com>
Signed-off-by: Natheir Abu-Dahab <20204834+nabudahab@users.noreply.github.com>
Co-authored-by: Jerry Zhao <qwertyuiopghb@gmail.com>
Signed-off-by: Natheir Abu-Dahab <20204834+nabudahab@users.noreply.github.com>
Fix implemented as suggested by @jerryz123

Signed-off-by: Natheir Abu-Dahab <20204834+nabudahab@users.noreply.github.com>
Removed unnecessary blank lines for cleaner code.

Signed-off-by: Natheir Abu-Dahab <20204834+nabudahab@users.noreply.github.com>
@nabudahab
Copy link
Author

nabudahab commented Jan 29, 2026

@jerryz123 I've implemented your suggested changes and tested --pcs with --pc. The interaction I defined was that -pc sets a global override PC and --pcs can set overrides on top of that for individual harts, --pcs also works without --pc with the unspecified harts simply starting at the PC defined by sim_t::get_entry_point().

Please let me know if there's anything else of concern or if this is ready for merge. Can someone approve the workflows again?

const int reset_vec_size = 8;

reg_t start_pc = cfg->start_pc.value_or(get_entry_point());
reg_t start_pc = cfg->start_pc.get(0).value_or(get_entry_point());
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pipeline fails. It seems to me that set_global should also set pc for hart 0 in order for this to work

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After some though I was wrong here. The problem is actually that you set pc in sim_t::proc_reset, overriding default ROM start address

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants