Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 80 additions & 1 deletion backends/instructions_appendix/all_instructions.golden.adoc
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
= Instruction Appendix
:doctype: book
:wavedrom: /workspace/riscv-unified-db/node_modules/.bin/wavedrom-cli
:wavedrom: /workspaces/riscv-unified-db/node_modules/.bin/wavedrom-cli
// Now the document header is complete and the wavedrom attribute is active.


Expand Down Expand Up @@ -16539,6 +16539,85 @@ Included in::
|===


[#udb:doc:inst:pause]
== pause

Synopsis::
Pause hint

Encoding::
[wavedrom, ,svg,subs='attributes',width="100%"]
....
{"reg":[{"bits":32,"name": 0x100000f,"type":2}]}
....

Description::
The PAUSE instruction is a HINT that indicates the current hart's rate of
instruction retirement should be temporarily reduced or paused. The duration
of its effect must be bounded and may be zero.

[NOTE]
====
Software can use the PAUSE instruction to reduce energy consumption
while executing spin-wait code sequences. Multithreaded cores might
temporarily relinquish execution resources to other harts when PAUSE is
executed. It is recommended that a PAUSE instruction generally be
included in the code sequence for a spin-wait loop.

A future extension might add primitives similar to the x86 MONITOR/MWAIT
instructions, which provide a more efficient mechanism to wait on writes
to a specific memory location. However, these instructions would not
supplant PAUSE. PAUSE is more appropriate when polling for non-memory
events, when polling for multiple events, or when software does not know
precisely what events it is polling for.

The duration of a PAUSE instruction's effect may vary significantly
within and among implementations. In typical implementations this
duration should be much less than the time to perform a context switch,
probably more on the rough order of an on-chip cache miss latency or a
cacheless access to main memory.

A series of PAUSE instructions can be used to create a cumulative delay
loosely proportional to the number of PAUSE instructions. In spin-wait
loops in portable code, however, only one PAUSE instruction should be
used before re-evaluating loop conditions, else the hart might stall
longer than optimal on some implementations, degrading system
performance.
====

PAUSE is encoded as a FENCE instruction with _pred_=`W`, _succ_=`0`, _fm_=`0`,
_xd_=`x0`, and _xs1_=`x0`.

[NOTE]
====
PAUSE is encoded as a hint within the FENCE opcode because some
implementations are expected to deliberately stall the PAUSE instruction
until outstanding memory transactions have completed. Because the
successor set is null, however, PAUSE does not _mandate_ any particular
memory ordering--hence, it truly is a HINT.

Like other FENCE instructions, PAUSE cannot be used within LR/SC
sequences without voiding the forward-progress guarantee.

The choice of a predecessor set of W is arbitrary, since the successor
set is null. Other HINTs similar to PAUSE might be encoded with other
predecessor sets.
====


Decode Variables::
pause has no decode variables.

Included in::
[options="autowrap,autowidth"]
|===
| Extension | Version

| *Zihintpause* | ~> 2.0.0

|===


[#udb:doc:inst:rem]
== rem

Expand Down
69 changes: 27 additions & 42 deletions spec/std/isa/inst/I/fence.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -144,15 +144,6 @@ access:
vs: always
vu: always
operation(): |
Boolean is_pause;
if (implemented?(ExtensionName::Zihintpause)) {
if ((pred == 1) && (succ == 0) && (xd == 0) && (xs1 == 0)) {
# this is a PAUSE instruction
is_pause = true;
}
}
Boolean pred_i = pred[3] == 1;
Boolean pred_o = pred[2] == 1;
Boolean pred_r = pred[1] == 1;
Expand All @@ -163,44 +154,38 @@ operation(): |
Boolean succ_r = succ[1] == 1;
Boolean succ_w = succ[0] == 1;
if (is_pause) {
pause();
} else {
# apply FIOM overrides
if (mode() == PrivilegeMode::S) {
if (CSR[menvcfg].FIOM == 1) {
if (pred_i) { pred_r = true; }
if (pred_o) { pred_w = true; }
if (succ_i) { succ_r = true; }
if (succ_o) { succ_w = true; }
}
} else if (mode() == PrivilegeMode::U) {
if ((CSR[menvcfg].FIOM | CSR[senvcfg].FIOM) == 1) {
if (pred_i) { pred_r = true; }
if (pred_o) { pred_w = true; }
if (succ_i) { succ_r = true; }
if (succ_o) { succ_w = true; }
}
} else if (mode() == PrivilegeMode::VS || mode() == PrivilegeMode::VU) {
if ((CSR[menvcfg].FIOM | CSR[henvcfg].FIOM) == 1) {
if (pred_i) { pred_r = true; }
if (pred_o) { pred_w = true; }
if (succ_i) { succ_r = true; }
if (succ_o) { succ_w = true; }
}
# apply FIOM overrides
if (mode() == PrivilegeMode::S) {
if (CSR[menvcfg].FIOM == 1) {
if (pred_i) { pred_r = true; }
if (pred_o) { pred_w = true; }
if (succ_i) { succ_r = true; }
if (succ_o) { succ_w = true; }
}
} else if (mode() == PrivilegeMode::U) {
if ((CSR[menvcfg].FIOM | CSR[senvcfg].FIOM) == 1) {
if (pred_i) { pred_r = true; }
if (pred_o) { pred_w = true; }
if (succ_i) { succ_r = true; }
if (succ_o) { succ_w = true; }
}
} else if (mode() == PrivilegeMode::VS || mode() == PrivilegeMode::VU) {
if ((CSR[menvcfg].FIOM | CSR[henvcfg].FIOM) == 1) {
if (pred_i) { pred_r = true; }
if (pred_o) { pred_w = true; }
if (succ_i) { succ_r = true; }
if (succ_o) { succ_w = true; }
}
fence(
pred_i, pred_o, pred_r, pred_w,
succ_i, succ_o, succ_r, succ_w
);
}
fence(
pred_i, pred_o, pred_r, pred_w,
succ_i, succ_o, succ_r, succ_w
);
hints:
- { $ref: inst/I/fence.tso.yaml# }
- { $ref: inst/Zihintpause/pause.yaml# }
pseudoinstructions:
- when: (pred == 1) && (succ == 0) && (xd == 0) && (xs1 == 0)
to: pause
- when: (pred == 4'b1111) && (succ == 4'b1111)
to: fence # fence => fence iorw,iorw

Expand Down
74 changes: 74 additions & 0 deletions spec/std/isa/inst/Zihintpause/pause.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# Copyright (c) Jordan Carlin
# SPDX-License-Identifier: BSD-3-Clause-Clear

# yaml-language-server: $schema=../../../../schemas/inst_schema.json

$schema: inst_schema.json#
kind: instruction
name: pause
long_name: Pause hint
description: |
The PAUSE instruction is a HINT that indicates the current hart's rate of
instruction retirement should be temporarily reduced or paused. The duration
of its effect must be bounded and may be zero.

[NOTE]
====
Software can use the PAUSE instruction to reduce energy consumption
while executing spin-wait code sequences. Multithreaded cores might
temporarily relinquish execution resources to other harts when PAUSE is
executed. It is recommended that a PAUSE instruction generally be
included in the code sequence for a spin-wait loop.

A future extension might add primitives similar to the x86 MONITOR/MWAIT
instructions, which provide a more efficient mechanism to wait on writes
to a specific memory location. However, these instructions would not
supplant PAUSE. PAUSE is more appropriate when polling for non-memory
events, when polling for multiple events, or when software does not know
precisely what events it is polling for.

The duration of a PAUSE instruction's effect may vary significantly
within and among implementations. In typical implementations this
duration should be much less than the time to perform a context switch,
probably more on the rough order of an on-chip cache miss latency or a
cacheless access to main memory.

A series of PAUSE instructions can be used to create a cumulative delay
loosely proportional to the number of PAUSE instructions. In spin-wait
loops in portable code, however, only one PAUSE instruction should be
used before re-evaluating loop conditions, else the hart might stall
longer than optimal on some implementations, degrading system
performance.
====

PAUSE is encoded as a FENCE instruction with _pred_=`W`, _succ_=`0`, _fm_=`0`,
_xd_=`x0`, and _xs1_=`x0`.

[NOTE]
====
PAUSE is encoded as a hint within the FENCE opcode because some
implementations are expected to deliberately stall the PAUSE instruction
until outstanding memory transactions have completed. Because the
successor set is null, however, PAUSE does not _mandate_ any particular
memory ordering--hence, it truly is a HINT.

Like other FENCE instructions, PAUSE cannot be used within LR/SC
sequences without voiding the forward-progress guarantee.

The choice of a predecessor set of W is arbitrary, since the successor
set is null. Other HINTs similar to PAUSE might be encoded with other
predecessor sets.
====

definedBy: Zihintpause
assembly: ""
encoding:
match: "00000001000000000000000000001111"
access:
s: always
u: always
vs: always
vu: always
data_independent_timing: false
operation(): |
pause();
Loading