Skip to content

Commit 15c37c5

Browse files
committed
fix(data): use hint for pause instruction
Replace `pseudoinstructions` inline in `fence.yaml` with hint references
1 parent 3d9129d commit 15c37c5

File tree

3 files changed

+181
-43
lines changed

3 files changed

+181
-43
lines changed

backends/instructions_appendix/all_instructions.golden.adoc

Lines changed: 80 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
= Instruction Appendix
22
:doctype: book
3-
:wavedrom: /workspace/riscv-unified-db/node_modules/.bin/wavedrom-cli
3+
:wavedrom: /workspaces/riscv-unified-db/node_modules/.bin/wavedrom-cli
44
// Now the document header is complete and the wavedrom attribute is active.
55

66

@@ -16539,6 +16539,85 @@ Included in::
1653916539
|===
1654016540

1654116541

16542+
[#udb:doc:inst:pause]
16543+
== pause
16544+
16545+
Synopsis::
16546+
Pause hint
16547+
16548+
Encoding::
16549+
[wavedrom, ,svg,subs='attributes',width="100%"]
16550+
....
16551+
{"reg":[{"bits":32,"name": 0x100000f,"type":2}]}
16552+
....
16553+
16554+
Description::
16555+
The PAUSE instruction is a HINT that indicates the current hart's rate of
16556+
instruction retirement should be temporarily reduced or paused. The duration
16557+
of its effect must be bounded and may be zero.
16558+
16559+
[NOTE]
16560+
====
16561+
Software can use the PAUSE instruction to reduce energy consumption
16562+
while executing spin-wait code sequences. Multithreaded cores might
16563+
temporarily relinquish execution resources to other harts when PAUSE is
16564+
executed. It is recommended that a PAUSE instruction generally be
16565+
included in the code sequence for a spin-wait loop.
16566+
16567+
A future extension might add primitives similar to the x86 MONITOR/MWAIT
16568+
instructions, which provide a more efficient mechanism to wait on writes
16569+
to a specific memory location. However, these instructions would not
16570+
supplant PAUSE. PAUSE is more appropriate when polling for non-memory
16571+
events, when polling for multiple events, or when software does not know
16572+
precisely what events it is polling for.
16573+
16574+
The duration of a PAUSE instruction's effect may vary significantly
16575+
within and among implementations. In typical implementations this
16576+
duration should be much less than the time to perform a context switch,
16577+
probably more on the rough order of an on-chip cache miss latency or a
16578+
cacheless access to main memory.
16579+
16580+
A series of PAUSE instructions can be used to create a cumulative delay
16581+
loosely proportional to the number of PAUSE instructions. In spin-wait
16582+
loops in portable code, however, only one PAUSE instruction should be
16583+
used before re-evaluating loop conditions, else the hart might stall
16584+
longer than optimal on some implementations, degrading system
16585+
performance.
16586+
====
16587+
16588+
PAUSE is encoded as a FENCE instruction with _pred_=`W`, _succ_=`0`, _fm_=`0`,
16589+
_xd_=`x0`, and _xs1_=`x0`.
16590+
16591+
[NOTE]
16592+
====
16593+
PAUSE is encoded as a hint within the FENCE opcode because some
16594+
implementations are expected to deliberately stall the PAUSE instruction
16595+
until outstanding memory transactions have completed. Because the
16596+
successor set is null, however, PAUSE does not _mandate_ any particular
16597+
memory ordering--hence, it truly is a HINT.
16598+
16599+
Like other FENCE instructions, PAUSE cannot be used within LR/SC
16600+
sequences without voiding the forward-progress guarantee.
16601+
16602+
The choice of a predecessor set of W is arbitrary, since the successor
16603+
set is null. Other HINTs similar to PAUSE might be encoded with other
16604+
predecessor sets.
16605+
====
16606+
16607+
16608+
Decode Variables::
16609+
pause has no decode variables.
16610+
16611+
Included in::
16612+
[options="autowrap,autowidth"]
16613+
|===
16614+
| Extension | Version
16615+
16616+
| *Zihintpause* | ~> 2.0.0
16617+
16618+
|===
16619+
16620+
1654216621
[#udb:doc:inst:rem]
1654316622
== rem
1654416623

spec/std/isa/inst/I/fence.yaml

Lines changed: 27 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -144,15 +144,6 @@ access:
144144
vs: always
145145
vu: always
146146
operation(): |
147-
Boolean is_pause;
148-
149-
if (implemented?(ExtensionName::Zihintpause)) {
150-
if ((pred == 1) && (succ == 0) && (xd == 0) && (xs1 == 0)) {
151-
# this is a PAUSE instruction
152-
is_pause = true;
153-
}
154-
}
155-
156147
Boolean pred_i = pred[3] == 1;
157148
Boolean pred_o = pred[2] == 1;
158149
Boolean pred_r = pred[1] == 1;
@@ -163,44 +154,38 @@ operation(): |
163154
Boolean succ_r = succ[1] == 1;
164155
Boolean succ_w = succ[0] == 1;
165156
166-
if (is_pause) {
167-
pause();
168-
} else {
169-
170-
# apply FIOM overrides
171-
if (mode() == PrivilegeMode::S) {
172-
if (CSR[menvcfg].FIOM == 1) {
173-
if (pred_i) { pred_r = true; }
174-
if (pred_o) { pred_w = true; }
175-
if (succ_i) { succ_r = true; }
176-
if (succ_o) { succ_w = true; }
177-
}
178-
} else if (mode() == PrivilegeMode::U) {
179-
if ((CSR[menvcfg].FIOM | CSR[senvcfg].FIOM) == 1) {
180-
if (pred_i) { pred_r = true; }
181-
if (pred_o) { pred_w = true; }
182-
if (succ_i) { succ_r = true; }
183-
if (succ_o) { succ_w = true; }
184-
}
185-
} else if (mode() == PrivilegeMode::VS || mode() == PrivilegeMode::VU) {
186-
if ((CSR[menvcfg].FIOM | CSR[henvcfg].FIOM) == 1) {
187-
if (pred_i) { pred_r = true; }
188-
if (pred_o) { pred_w = true; }
189-
if (succ_i) { succ_r = true; }
190-
if (succ_o) { succ_w = true; }
191-
}
157+
# apply FIOM overrides
158+
if (mode() == PrivilegeMode::S) {
159+
if (CSR[menvcfg].FIOM == 1) {
160+
if (pred_i) { pred_r = true; }
161+
if (pred_o) { pred_w = true; }
162+
if (succ_i) { succ_r = true; }
163+
if (succ_o) { succ_w = true; }
164+
}
165+
} else if (mode() == PrivilegeMode::U) {
166+
if ((CSR[menvcfg].FIOM | CSR[senvcfg].FIOM) == 1) {
167+
if (pred_i) { pred_r = true; }
168+
if (pred_o) { pred_w = true; }
169+
if (succ_i) { succ_r = true; }
170+
if (succ_o) { succ_w = true; }
171+
}
172+
} else if (mode() == PrivilegeMode::VS || mode() == PrivilegeMode::VU) {
173+
if ((CSR[menvcfg].FIOM | CSR[henvcfg].FIOM) == 1) {
174+
if (pred_i) { pred_r = true; }
175+
if (pred_o) { pred_w = true; }
176+
if (succ_i) { succ_r = true; }
177+
if (succ_o) { succ_w = true; }
192178
}
193-
194-
fence(
195-
pred_i, pred_o, pred_r, pred_w,
196-
succ_i, succ_o, succ_r, succ_w
197-
);
198179
}
180+
181+
fence(
182+
pred_i, pred_o, pred_r, pred_w,
183+
succ_i, succ_o, succ_r, succ_w
184+
);
199185
hints:
200186
- { $ref: inst/I/fence.tso.yaml# }
187+
- { $ref: inst/Zihintpause/pause.yaml# }
201188
pseudoinstructions:
202-
- when: (pred == 1) && (succ == 0) && (xd == 0) && (xs1 == 0)
203-
to: pause
204189
- when: (pred == 4'b1111) && (succ == 4'b1111)
205190
to: fence # fence => fence iorw,iorw
206191

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
# Copyright (c) Jordan Carlin
2+
# SPDX-License-Identifier: BSD-3-Clause-Clear
3+
4+
# yaml-language-server: $schema=../../../../schemas/inst_schema.json
5+
6+
$schema: inst_schema.json#
7+
kind: instruction
8+
name: pause
9+
long_name: Pause hint
10+
description: |
11+
The PAUSE instruction is a HINT that indicates the current hart's rate of
12+
instruction retirement should be temporarily reduced or paused. The duration
13+
of its effect must be bounded and may be zero.
14+
15+
[NOTE]
16+
====
17+
Software can use the PAUSE instruction to reduce energy consumption
18+
while executing spin-wait code sequences. Multithreaded cores might
19+
temporarily relinquish execution resources to other harts when PAUSE is
20+
executed. It is recommended that a PAUSE instruction generally be
21+
included in the code sequence for a spin-wait loop.
22+
23+
A future extension might add primitives similar to the x86 MONITOR/MWAIT
24+
instructions, which provide a more efficient mechanism to wait on writes
25+
to a specific memory location. However, these instructions would not
26+
supplant PAUSE. PAUSE is more appropriate when polling for non-memory
27+
events, when polling for multiple events, or when software does not know
28+
precisely what events it is polling for.
29+
30+
The duration of a PAUSE instruction's effect may vary significantly
31+
within and among implementations. In typical implementations this
32+
duration should be much less than the time to perform a context switch,
33+
probably more on the rough order of an on-chip cache miss latency or a
34+
cacheless access to main memory.
35+
36+
A series of PAUSE instructions can be used to create a cumulative delay
37+
loosely proportional to the number of PAUSE instructions. In spin-wait
38+
loops in portable code, however, only one PAUSE instruction should be
39+
used before re-evaluating loop conditions, else the hart might stall
40+
longer than optimal on some implementations, degrading system
41+
performance.
42+
====
43+
44+
PAUSE is encoded as a FENCE instruction with _pred_=`W`, _succ_=`0`, _fm_=`0`,
45+
_xd_=`x0`, and _xs1_=`x0`.
46+
47+
[NOTE]
48+
====
49+
PAUSE is encoded as a hint within the FENCE opcode because some
50+
implementations are expected to deliberately stall the PAUSE instruction
51+
until outstanding memory transactions have completed. Because the
52+
successor set is null, however, PAUSE does not _mandate_ any particular
53+
memory ordering--hence, it truly is a HINT.
54+
55+
Like other FENCE instructions, PAUSE cannot be used within LR/SC
56+
sequences without voiding the forward-progress guarantee.
57+
58+
The choice of a predecessor set of W is arbitrary, since the successor
59+
set is null. Other HINTs similar to PAUSE might be encoded with other
60+
predecessor sets.
61+
====
62+
63+
definedBy: Zihintpause
64+
assembly: ""
65+
encoding:
66+
match: "00000001000000000000000000001111"
67+
access:
68+
s: always
69+
u: always
70+
vs: always
71+
vu: always
72+
data_independent_timing: false
73+
operation(): |
74+
pause();

0 commit comments

Comments
 (0)