Why Perforce in VLSI?
Perforce Helix Core is the dominant version control system in ASIC design. Most major semiconductor companies — Qualcomm, NVIDIA, Intel, Broadcom, MediaTek — run on Perforce internally. If you join a chip design team, odds are you will use p4 from day one.
| Capability | Why It Matters in VLSI |
|---|---|
| Scales to millions of files | A full chip project has RTL, synthesis scripts, timing libraries (.lib/.db), LEF/DEF, GDS — millions of files across all process nodes |
| Binary file handling | GDS, .lib, .lef, simulation waveforms (.vcd/.vpd) are large binaries — Perforce tracks them without delta bloat |
| Atomic changelists | A numbered changelist bundles all related edits; rollback is surgical and atomic |
| Exclusive locks | PDK files, foundry IP, and GDS must not have concurrent edits — p4 lock enforces this |
| Server-side storage | Only the files you need are synced locally; a 500 GB depot doesn't fill your workstation |
| Streams branching | Mainline → development → release hierarchy maps naturally to RTL tape-in flow |
Perforce Architecture
Perforce has three layers. Understanding them prevents the most common beginner mistakes.
The central repository living on the Helix Core server. Stores every version of every file. Addressed as //depot/...
Your local checkout, defined by a client spec. Maps depot paths to local disk paths. One user can have many clients for different tasks.
A numbered set of file edits submitted atomically. The fundamental unit of work in Perforce — equivalent to a commit, but pre-planned.
A pending changelist saved to the server without submitting. Other engineers (or CI) can unshelve and review your work-in-progress.
A managed branch with explicit parent/child relationships. Perforce enforces flow direction (changes flow up to mainline, down to releases).
A snapshot tagging specific file revisions. Used to stamp a tape-in checkpoint or a confirmed-good synthesis closure.
/home/eng/proj/rtl/top.v. Never confuse the two — p4 where top.v shows both.Client Setup
Environment Variables
Set these once in your shell profile or via p4 set:
# Add to ~/.bashrc or ~/.bash_profile
export P4PORT=perforce.chipco.com:1666 # server:port
export P4USER=jsmith # your Perforce username
export P4CLIENT=jsmith-rtl-dev # your client spec name
export P4EDITOR=vim # editor for changelists
# Or set persistently via p4 (stored in ~\.p4enviro on Windows)
p4 set P4PORT=perforce.chipco.com:1666
p4 set P4USER=jsmith
p4 set P4CLIENT=jsmith-rtl-dev
# Verify
p4 info
Creating a Client Spec
A client spec defines which depot paths map to which local directories. Run p4 client to open an editor:
Client: jsmith-rtl-dev
Owner: jsmith
Host: eng-workstation-07
Root: /home/jsmith/proj
View:
//depot/proj/rtl/... //jsmith-rtl-dev/rtl/...
//depot/proj/dv/... //jsmith-rtl-dev/dv/...
//depot/proj/syn/... //jsmith-rtl-dev/syn/...
# Exclude PDK — too large to sync locally
-//depot/pdk/... //jsmith-rtl-dev/pdk/...
Login
p4 login # prompts for password, creates a ticket
p4 login -s # show ticket status and expiry
p4 logout # invalidate ticket
Daily Workflow
# 1. Sync latest
p4 sync # sync all mapped files
p4 sync //depot/proj/rtl/... # sync a specific subtree
p4 sync @label_name # sync to a specific label
p4 sync @12345 # sync to changelist 12345
# 2. Open for edit
p4 edit rtl/core/alu.v # check out a file
p4 edit rtl/... # check out all files in rtl/
p4 add rtl/core/alu_tb.sv # mark a new file to add
p4 delete rtl/old/legacy.v # mark a file for deletion
# 3. Check your pending edits
p4 opened # list all opened files
p4 status # show local vs depot diff
p4 diff rtl/core/alu.v # diff a single file
# Revert if you changed your mind
p4 revert rtl/core/alu.v # undo a single file
p4 revert -a # revert files with no actual changes
# 4. Submit
p4 submit -d "Fix carry ripple in alu adder" # quick submit
p4 submit # opens editor for changelist
p4 submit -c 45678 # submit a specific numbered CL
p4 reconcile to detect and open the changed files retroactively.Changelists
A changelist (CL) is a numbered, atomic set of file changes. Every submit creates one. You can also create pending changelists to group work-in-progress before submitting.
Creating and Managing Pending Changelists
# Create a new numbered pending CL
p4 change # opens editor — fill in Description
# → Perforce assigns a CL number, e.g. 45901
# Move an opened file to a specific CL
p4 reopen -c 45901 rtl/core/alu.v
# List pending CLs
p4 changes -s pending -u jsmith
# Edit CL description
p4 change 45901
# Delete an empty pending CL
p4 change -d 45901
Inspecting Submitted Changelists
# Show details of a submitted CL
p4 describe 45678
# Show all CLs in a path
p4 changes //depot/proj/rtl/...
# Last 10 CLs by any user
p4 changes -m 10 //depot/proj/...
# CLs by a specific user
p4 changes -u jsmith -m 20
-c CL#. For any real work, create a numbered CL with a description so your intent is clear to reviewers and release engineers.Shelving (p4 shelve)
Shelving saves your pending changes to the server without submitting them. Other engineers can unshelve your shelf for review or testing. It's the Perforce equivalent of git stash push — but server-side and shareable.
# Shelve all files in a pending CL
p4 shelve -c 45901
# Shelve only specific files
p4 shelve -c 45901 rtl/core/alu.v rtl/core/alu_tb.sv
# Update a shelf (re-shelve after more edits)
p4 shelve -f -c 45901 # -f to force overwrite existing shelf
# Another engineer unshelves your work
p4 unshelve -s 45901 # into their own default CL
p4 unshelve -s 45901 -c 46000 # into a specific CL
# Delete a shelf
p4 shelve -d -c 45901
# List shelved CLs
p4 changes -s shelved -u jsmith
Stash Workaround (no Perforce shelve access)
If your site doesn't allow shelving, create a WIP branch stream or generate a patch:
# Generate a patch from diff output
p4 diff -du > wip.patch
# Revert, do other work, then apply the patch
p4 revert ...
patch -p0 < wip.patch
Streams & Branching
Perforce Streams are managed branches with a defined parent/child hierarchy. Changes must flow from child streams up through parents (copy up) and from parents back down to children (merge down). This enforces clean integration discipline — critical for multi-project chip designs.
The single source of truth. Equivalent to Git main/trunk. No parent. All stable, taped-in RTL lives here.
Child of mainline. Feature work happens here. Multiple dev streams can exist in parallel for different IPs.
Child of mainline, cut at tape-in. Only bug fixes merge in. Post-silicon patches and mask revisions come from release streams.
No files of its own — filters a parent stream's view. Useful to give a sub-team access to only their IP block.
# List streams
p4 streams //depot/proj/...
# Create a development stream
p4 stream -t development -P //depot/proj/main //depot/proj/dev/alu-v2
# Switch your client to a stream
p4 client -S //depot/proj/dev/alu-v2
# After making and submitting changes in dev — merge down from parent
p4 merge # pulls latest mainline changes into your dev stream
p4 resolve -am # auto-merge non-conflicting files
p4 resolve # interactive resolve for conflicts
p4 submit -d "Merge latest mainline into alu-v2 dev"
# Promote dev work up to mainline (copy up)
p4 copy //depot/proj/dev/alu-v2/... //depot/proj/main/...
p4 submit -d "Copy alu-v2 feature to mainline"
Labels (Tape-in Snapshots)
# Create a label at current sync point
p4 label proj_tapeout_q2_2026
p4 labelsync -l proj_tapeout_q2_2026
# List all labels
p4 labels
# Sync to a label
p4 sync @proj_tapeout_q2_2026
History, Diff & Annotate
# File revision history
p4 filelog rtl/core/alu.v # show all revisions
p4 filelog -m 10 rtl/core/alu.v # last 10 changes only
# Diff between revisions
p4 diff2 rtl/core/alu.v#4 rtl/core/alu.v#7 # between two revisions
p4 diff rtl/core/alu.v # workspace vs depot head
# Annotate (blame) — who changed each line
p4 annotate rtl/core/alu.v
p4 annotate -c rtl/core/alu.v # show CL numbers instead of revisions
# Find which CL introduced a specific string
p4 grep -r -n "set_multicycle_path" //depot/proj/syn/...
# Show changelist description + diff
p4 describe -du 45678
# Print a file at a specific revision
p4 print rtl/core/alu.v#3
p4 print @proj_tapeout_q2_2026 //depot/proj/rtl/core/alu.v
p4 integrate (Merging)
p4 integrate (or its alias p4 merge in Streams) propagates changes between branches. For Streams, use the Streams flow commands; for classic depot branches, use integrate directly.
# Integrate (cherry-pick) a single CL from dev to main
p4 integrate -c 45678 //depot/proj/dev/alu-v2/... //depot/proj/main/...
# Integrate a range of CLs
p4 integrate @45600,45700 //depot/proj/dev/... //depot/proj/main/...
# Resolve conflicts after integrate
p4 resolve -am # accept merge for auto-resolvable files
p4 resolve -at # accept theirs (source branch wins)
p4 resolve -ay # accept yours (target branch wins)
p4 resolve # launch interactive resolve for each conflict
p4 resolve -n # preview without resolving
# After resolving, submit
p4 submit -d "Integrate alu timing fix from dev to main"
# Undo a bad submit (reverse integrate)
p4 integrate -r -c 45901 //depot/proj/main/...
p4 submit -d "Revert bad CL 45901 via reverse integrate"
VLSI-Specific Workflows
Handling Binary IP Files (GDS, Liberty, LEF)
# Mark binary files so Perforce doesn't try to diff them
p4 add -t binary pdk/gds/stdcell_9t.gds
p4 add -t binary libs/timing/tt_0v85_25c.db
# Lock a PDK file so only one engineer can edit at a time
p4 lock pdk/rules/drc_rules_v3.2.rule
# Release the lock
p4 unlock pdk/rules/drc_rules_v3.2.rule
# See who has locked files
p4 opened -a | grep -i "lock"
p4 reconcile — Recover from Forgotten p4 edit
# You edited files without p4 edit first — Perforce didn't know
# Reconcile detects and opens them for you
p4 reconcile rtl/core/...
# Preview what reconcile would open
p4 reconcile -n rtl/core/...
Tagging a Synthesis Run
# Create a label for the RTL state at synthesis sign-off
p4 label synth_close_q3_2026
# Add label description in editor — then
p4 labelsync -l synth_close_q3_2026 //depot/proj/rtl/...
# Record which synthesis options were used
p4 add syn/reports/area_rpt_q3_2026.txt
p4 submit -d "Archive synthesis closure report Q3-2026"
Multiple Workspaces for Parallel Runs
# DV engineer runs regression at CL 45000; RTL engineer keeps editing
# Create a separate client for the regression workspace
p4 client -t jsmith-rtl-dev jsmith-regress-run
# Change root: /home/jsmith/regress
# Sync the regression workspace to a specific CL
P4CLIENT=jsmith-regress-run p4 sync @45000
.p4ignore — Perforce's .gitignore Equivalent
# ~/.p4ignore (or set P4IGNORE=.p4ignore in project root)
work/
*.wlf
*.vcd
*.vpd
*.fsdb
*.log
*.rpt
*.ddc
*.svdb
simv
simv.daidir/
csrc/
AN.DB/
*.jou
P4IGNORE=.p4ignore in your environment so p4 reconcile and p4 add skip simulation output automatically.Quick Reference
| Command | What It Does |
|---|---|
| p4 sync | Sync local workspace to depot head |
| p4 sync @CL | Sync to a specific changelist number |
| p4 edit FILE | Check out a file for editing |
| p4 add FILE | Mark a new file to be added |
| p4 delete FILE | Mark a file for deletion |
| p4 revert FILE | Undo checkout, restore read-only |
| p4 revert -a | Revert files with no actual changes |
| p4 submit -d "msg" | Submit default CL to depot |
| p4 change | Create/edit a numbered pending CL |
| p4 shelve -c CL | Save pending CL to server without submitting |
| p4 unshelve -s CL | Restore a shelved CL to workspace |
| p4 opened | List all files you have open |
| p4 status | Show workspace vs depot differences |
| p4 reconcile | Detect edits made without p4 edit |
| p4 diff FILE | Diff workspace vs depot head |
| p4 diff2 FILE#R1 FILE#R2 | Diff between two depot revisions |
| p4 filelog FILE | Show revision history of a file |
| p4 annotate FILE | Show who changed each line (blame) |
| p4 changes //path/... | List submitted CLs in a path |
| p4 describe CL | Show CL description + file list + diff |
| p4 integrate -c CL FROM TO | Cherry-pick a CL between branches |
| p4 resolve -am | Auto-merge non-conflicting integrate results |
| p4 lock FILE | Exclusive lock on a file |
| p4 label NAME | Create a snapshot label |
| p4 labelsync -l NAME | Stamp current sync state into a label |
| p4 streams //depot/... | List streams under a depot path |
| p4 merge | Merge-down from parent stream in Streams workflow |
| p4 copy FROM TO | Copy-up (promote) to parent stream |
| p4 where FILE | Show depot path ↔ local path mapping |
| p4 info | Show connection info and client details |
Common Q&A
What's the difference between p4 sync and p4 update?
p4 sync syncs all mapped files to depot head (or the specified revision), overwriting even files you have open for edit — it's destructive if used carelessly. p4 update is safer: it syncs depot changes but skips files you have open, preserving your in-progress edits. For day-to-day work, prefer p4 update if it's available (P4V GUI uses it by default). For CI builds and clean workspaces, use p4 sync.
I edited a file without running p4 edit first. What do I do?
p4 reconcile in the directory where you made edits. Perforce compares your local files with the depot read-only copies and automatically opens the ones that differ for edit, marks missing files for delete, and flags new files for add. Preview first with p4 reconcile -n to see what it would do before committing.
How do I undo a submitted changelist?
p4 integrate -r -c <bad-CL> //depot/path/... followed by p4 resolve -ay and then p4 submit. This creates a new changelist that exactly undoes the bad one, while preserving integration history so future merges handle the reversal correctly. Never manually edit the affected files to revert — you'll break Perforce's merge tracking and cause headaches for the integration team.
How do streams differ from classic Perforce branches?
How do I share work-in-progress with a colleague without submitting?
p4 shelve -c <CL> to save your pending changelist to the server. Send your colleague the CL number. They run p4 unshelve -s <CL> to pull your changes into their own workspace for review, simulation, or CI testing. You can update the shelf repeatedly with p4 shelve -f -c <CL> as you make more changes. Most code review tools (Swarm, Crucible) integrate directly with shelved CLs.