Skip to content

Commit 6580857

Browse files
author
Derek Hower
committed
Add CSR list to manual
1 parent fbe6a41 commit 6580857

File tree

9 files changed

+258
-12
lines changed

9 files changed

+258
-12
lines changed

.github/workflows/pages.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,12 @@ jobs:
4343
run: ./bin/build_container
4444
- name: Setup project
4545
run: ./bin/setup
46+
- name: Build manual
47+
run: ./do gen:html_manual MANUAL_NAME=isa VERSIONS=all
4648
- name: Build html documentation for generic_rv64
4749
run: ./do gen:html[generic_rv64]
4850
- name: Generate YARD docs
4951
run: ./do gen:tool_doc
50-
- name: Build manual
51-
run: ./do gen:html_manual MANUAL_NAME=isa VERSIONS=all
5252
- name: Create _site/example_cfg
5353
run: mkdir -p _site/example_cfg
5454
- name: Create _site/manual

arch/manual/isa/20240411/contents.yaml

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ volumes:
6868
#/End of Vector appendices
6969
extensions:
7070
- [I, "2.1.0"]
71+
- [U, "1.12.0"]
7172
# - [E, "2.0"]
7273
# - [RVI64, "2.1"]
7374
# - [RVI128, "1.7"]
@@ -176,4 +177,43 @@ volumes:
176177
- name: Andrew Waterman
177178
178179
organization: SiFive, Inc.
179-
url: https://www.sifive.com/
180+
url: https://www.sifive.com/
181+
chapters:
182+
- riscv-isa-manual/src/priv-preface.adoc
183+
- riscv-isa-manual/src/priv-intro.adoc
184+
- riscv-isa-manual/src/priv-csrs.adoc
185+
- riscv-isa-manual/src/machine.adoc
186+
- riscv-isa-manual/src/smstateen.adoc
187+
- riscv-isa-manual/src/indirect-csr.adoc
188+
- riscv-isa-manual/src/smepmp.adoc
189+
- riscv-isa-manual/src/smcntrpmf.adoc
190+
- riscv-isa-manual/src/rnmi.adoc
191+
- riscv-isa-manual/src/smcdeleg.adoc
192+
- riscv-isa-manual/src/supervisor.adoc
193+
- riscv-isa-manual/src/sstc.adoc
194+
- riscv-isa-manual/src/sscofpmf.adoc
195+
- riscv-isa-manual/src/hypervisor.adoc
196+
- riscv-isa-manual/src/priv-insns.adoc
197+
- riscv-isa-manual/src/priv-history.adoc
198+
- riscv-isa-manual/src/bibliography.adoc
199+
extensions:
200+
- [Smstateen, "1.0.0"]
201+
- [Smcsrind, "1.0.0"]
202+
- [Sscsrind, "1.0.0"]
203+
- [Smepmp, "1.0.0"]
204+
- [Smcntrpmf, "1.0.0"]
205+
- [Smrnmi, "0.5.0"]
206+
- [Smcdeleg, "1.0.0"]
207+
- [S, "1.12.0"]
208+
- [Sv32, "1.13.0"]
209+
- [Sv39, "1.13.0"]
210+
- [Sv48, "1.13.0"]
211+
- [Sv57, "1.13.0"]
212+
- [Svnapot, "1.0.0"]
213+
- [Svpbmt, "1.0.0"]
214+
- [Svinval, "1.0.0"]
215+
- [Svadu, "1.0.0"]
216+
- [Svvptc, "1.0.0"]
217+
- [Sstc, "1.0.0"]
218+
- [Sscofpmf, "1.0.0"]
219+
- [H, "1.0.0"]

backends/manual/tasks.rake

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,26 @@ rule %r{#{MANUAL_GEN_DIR}/.*/.*/antora/modules/insts/pages/.*.adoc} => [
230230
File.write t.name, AntoraUtils.resolve_links(erb.result(binding))
231231
end
232232

233+
# rule to create csr appendix page
234+
rule %r{#{MANUAL_GEN_DIR}/.*/.*/antora/modules/csrs/pages/.*.adoc} => [
235+
__FILE__,
236+
"gen:arch",
237+
($root / "backends" / "manual" / "templates" / "csr.adoc.erb").to_s
238+
] do |t|
239+
csr_name = File.basename(t.name, ".adoc")
240+
241+
arch_def = arch_def_for("_")
242+
csr = arch_def.csr(csr_name)
243+
raise "Can't find csr '#{csr_name}'" if csr.nil?
244+
245+
csr_template_path = $root / "backends" / "manual" / "templates" / "csr.adoc.erb"
246+
erb = ERB.new(csr_template_path.read, trim_mode: "-")
247+
erb.filename = csr_template_path.to_s
248+
249+
FileUtils.mkdir_p File.dirname(t.name)
250+
File.write t.name, AntoraUtils.resolve_links(erb.result(binding))
251+
end
252+
233253
# rule to create IDL function appendix page
234254
rule %r{#{MANUAL_GEN_DIR}/.*/.*/antora/modules/funcs/pages/funcs.adoc} => [
235255
__FILE__,
@@ -274,7 +294,7 @@ rule %r{#{MANUAL_GEN_DIR}/.*/top/.*/antora/playbook.yml} => proc { |tname|
274294
File.write t.name, erb.result(binding)
275295
end
276296

277-
file $root / "ext" / "riscv-isa_manual" / "README.md" do
297+
file $root / "ext" / "riscv-isa-manual" / "README.md" do
278298
sh "git submodule update --init ext/riscv-isa-manual"
279299
end
280300

@@ -345,6 +365,9 @@ namespace :gen do
345365
version.instructions.each do |inst|
346366
Rake::Task[antora_path / "modules" / "insts" / "pages" / "#{inst.name}.adoc"].invoke
347367
end
368+
version.csrs.each do |csr|
369+
Rake::Task[antora_path / "modules" / "csrs" / "pages" / "#{csr.name}.adoc"].invoke
370+
end
348371
end
349372

350373
playbook_path = MANUAL_GEN_DIR / ENV["MANUAL_NAME"] / "top" / output_hash / "antora" / "playbook.yml"
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
:tabs-sync-option:
2+
3+
[#csrs-<%= csr.name.gsub('.', '_') %>,reftext=<%= csr.name %>]
4+
= <%= csr.name %>
5+
6+
*<%= csr.long_name %>*
7+
8+
<%= csr.description %>
9+
10+
== Attributes
11+
[%autowidth]
12+
|===
13+
h| CSR Address | <%= "0x#{csr.address.to_s(16)}" %>
14+
<%- if csr.priv_mode == 'VS' -%>
15+
h| Virtual CSR Address | <%= "0x#{csr.virtual_address.to_s(16)}" %>
16+
<%- end -%>
17+
<%- if csr.dynamic_length?(arch_def) -%>
18+
h| Length | <%= csr.length_pretty(arch_def) %>
19+
<%- else -%>
20+
h| Length | <%= csr.length_pretty(arch_def) %>-bit
21+
<%- end -%>
22+
h| Privilege Mode | <%= csr.priv_mode %>
23+
|===
24+
25+
== Format
26+
<%- unless csr.dynamic_length?(arch_def) || csr.fields.any? { |f| f.dynamic_location?(arch_def) } -%>
27+
<%# CSR has a known static length, so there is only one format to display -%>
28+
.<%= csr.name %> format
29+
[wavedrom, ,svg,subs='attributes',width="100%"]
30+
....
31+
<%= JSON.dump csr.wavedrom_desc(arch_def, 64) %>
32+
....
33+
<%- else -%>
34+
<%# CSR has a dynamic length, or a field has a dynamic location,
35+
so there is more than one format to display -%>
36+
This CSR format changes dynamically.
37+
38+
.<%= csr.name %> Format when <%= csr.length_cond32 %>
39+
[wavedrom, ,svg,subs='attributes',width="100%"]
40+
....
41+
<%= JSON.dump csr.wavedrom_desc(arch_def, 32) %>
42+
....
43+
44+
.<%= csr.name %> Format when <%= csr.length_cond64 %>
45+
[wavedrom, ,svg,subs='attributes',width="100%"]
46+
....
47+
<%= JSON.dump csr.wavedrom_desc(arch_def, 64) %>
48+
....
49+
<%- end -%>
50+
51+
== Field Summary
52+
53+
[%autowidth,float="center",align="center",cols="^,<,<,<",options="header",role="stretch"]
54+
|===
55+
|Name | Location | Type | Reset Value
56+
57+
<%- csr.fields.each do |field| -%>
58+
| xref:<%=csr.name%>-<%=field.name%>-def[`<%= field.name %>`]
59+
| <%= field.location_pretty(arch_def) %>
60+
| <%= field.type_pretty(arch_def) %>
61+
| <%= field.reset_value_pretty(arch_def) %>
62+
63+
<%- end -%>
64+
|===
65+
66+
== Fields
67+
68+
<%- if csr.fields.empty? -%>
69+
This CSR has no fields. However, it must still exist (not cause an `Illegal Instruction` trap) and always return zero on a read.
70+
<%- else -%>
71+
72+
<%- csr.fields.each do |field| -%>
73+
[[<%=csr.name%>-<%=field.name%>-def]]
74+
=== `<%= field.name %>`
75+
76+
[example]
77+
****
78+
Location::
79+
<%= field.location_pretty(arch_def) %>
80+
81+
Description::
82+
<%= field.description %>
83+
84+
Type::
85+
<%= field.type_pretty(arch_def) %>
86+
87+
Reset value::
88+
<%= field.reset_value_pretty(arch_def) %>
89+
90+
****
91+
92+
<%- end -%>
93+
<%- end -%>
94+
95+
<%- if csr.fields.map(&:has_custom_sw_write?).any? -%>
96+
== Software write
97+
98+
This CSR may store a value that is different from what software attempts to write.
99+
100+
When a software write occurs (_e.g._, through `csrrw`), the following determines the
101+
written value:
102+
103+
[idl]
104+
----
105+
<%- csr.fields.each do |field| -%>
106+
<%- if field.has_custom_sw_write? -%>
107+
<%= field.name %> = <%= field["sw_write(csr_value)"] %>
108+
<%- else -%>
109+
<%= field.name %> = csr_value.<%= field.name %>
110+
<%- end -%>
111+
<%- end -%>
112+
----
113+
<%- end -%>
114+
115+
<%- if csr.has_custom_sw_read? -%>
116+
== Software read
117+
118+
This CSR may return a value that is different from what is stored in hardware.
119+
120+
[source,idl,subs="specialchars,macros"]
121+
----
122+
<%= csr.sw_read_ast(arch_def.idl_compiler).gen_adoc %>
123+
----
124+
<%- end -%>
125+

backends/manual/templates/instruction.adoc.erb

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,6 @@ RV64::
117117
----
118118
<%= inst.operation_ast(inst.arch_def.idl_compiler).gen_adoc %>
119119
----
120-
====
121120
<%- end -%>
122121

123122
<%# exception_list = inst.reachable_exceptions_str(inst.arch_def.sym_table_64, 64) -%>

backends/manual/templates/isa_nav.adoc.erb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,10 @@
1111
* xref:insts:<%= inst.name %>.adoc[<%= inst.name %>]
1212
<%- end -%>
1313

14+
.Alphabetical list of CSRs
15+
<%- manual_version.csrs.sort { |a, b| a.name <=> b.name }.each do |csr| -%>
16+
* xref:csrs:<%= csr.name %>.adoc[<%= csr.name %>]
17+
<%- end -%>
18+
1419
.Execution functions (IDL)
1520
* xref:funcs:funcs.adoc[Functions]

lib/arch_obj_models/csr.rb

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -154,9 +154,35 @@ def dynamic_length?(arch_def)
154154
# !@data["length"].is_a?(Integer) && (@data["length"] != "MXLEN")
155155
end
156156

157+
# @param arch_def [ArchDef] Architecture definition
158+
# @return [Integer] Smallest length of the CSR in any mode
159+
def min_length(arch_def)
160+
case @data["length"]
161+
when "MXLEN", "SXLEN", "VSXLEN"
162+
32
163+
when Integer
164+
@data["length"]
165+
else
166+
raise "Unexpected length"
167+
end
168+
end
169+
170+
# @param arch_def [ArchDef] Architecture definition
171+
# @return [Integer] Largest length of the CSR in any mode
172+
def max_length(arch_def)
173+
case @data["length"]
174+
when "MXLEN", "SXLEN", "VSXLEN"
175+
64
176+
when Integer
177+
@data["length"]
178+
else
179+
raise "Unexpected length"
180+
end
181+
end
182+
157183
# @param arch_def [ArchDef] A configuration (can be nil if the lenth is not dependent on a config parameter)
158184
# @param effective_xlen [Integer] The effective xlen, needed since some fields change location with XLEN. If the field location is not determined by XLEN, then this parameter can be nil
159-
# @return [Integer] Length, in bits, of the CSR
185+
# @return [Integer] Length, in bits, of the CSR, given effective_xlen
160186
def length(arch_def, effective_xlen = nil)
161187
case @data["length"]
162188
when "MXLEN"
@@ -167,7 +193,7 @@ def length(arch_def, effective_xlen = nil)
167193
@data["base"]
168194
else
169195
# don't know MXLEN
170-
raise ArgumentError, "effective_xlen is required when length is MXLEN and arch_def is generic" if effective_xlen.nil?
196+
raise ArgumentError, "for CSR #{name}: effective_xlen is required when length is MXLEN and arch_def is generic" if effective_xlen.nil?
171197

172198
effective_xlen
173199
end

lib/arch_obj_models/csr_field.rb

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -532,17 +532,29 @@ def location(arch_def, effective_xlen = nil)
532532
raise "Missing location for #{csr.name}.#{name} (#{key})?" unless @data.key?(key)
533533

534534
if @data[key].is_a?(Integer)
535-
if @data[key] > csr.length(arch_def, effective_xlen || @data["base"])
536-
raise "Location (#{key} = #{@data[key]}) is past the csr length (#{csr.length(arch_def, effective_xlen)}) in #{csr.name}.#{name}"
535+
if (arch_def.is_a?(ImplArchDef))
536+
if @data[key] > csr.length(arch_def, effective_xlen || @data["base"])
537+
raise "Location (#{key} = #{@data[key]}) is past the csr length (#{csr.length(arch_def, effective_xlen)}) in #{csr.name}.#{name}"
538+
end
539+
else
540+
if @data[key] > csr.max_length(arch_def)
541+
raise "Location (#{key} = #{@data[key]}) is past the max csr length (#{csr.max_length(arch_def)}) in #{csr.name}.#{name}"
542+
end
537543
end
538544

539545
@data[key]..@data[key]
540546
elsif @data[key].is_a?(String)
541547
e, s = @data[key].split("-").map(&:to_i)
542548
raise "Invalid location" if s > e
543549

544-
if e > csr.length(arch_def, effective_xlen)
545-
raise "Location (#{key} = #{@data[key]}) is past the csr length (#{csr.length(arch_def, effective_xlen)}) in #{csr.name}.#{name}"
550+
if (arch_def.is_a?(ImplArchDef))
551+
if e > csr.length(arch_def, effective_xlen)
552+
raise "Location (#{key} = #{@data[key]}) is past the csr length (#{csr.length(arch_def, effective_xlen)}) in #{csr.name}.#{name}"
553+
end
554+
else
555+
if e > csr.max_length(arch_def)
556+
raise "Location (#{key} = #{@data[key]}) is past the max csr length (#{csr.max_length(arch_def)}) in #{csr.name}.#{name}"
557+
end
546558
end
547559

548560
s..e
@@ -578,12 +590,14 @@ def location_pretty(arch_def)
578590
if dynamic_location?(arch_def)
579591
condition =
580592
case csr.priv_mode
593+
when "M"
594+
"CSR[misa].MXL == %%"
581595
when "S"
582596
"CSR[mstatus].SXL == %%"
583597
when "VS"
584598
"CSR[hstatus].VSXL == %%"
585599
else
586-
raise "Unexpected priv mode"
600+
raise "Unexpected priv mode #{csr.priv_mode} for #{csr.name}"
587601
end
588602

589603
<<~LOC

lib/arch_obj_models/manual.rb

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,4 +171,18 @@ def instructions
171171
end
172172
@instructions
173173
end
174+
175+
# @return [Array<Csr>] All csrs defined in this version
176+
def csrs
177+
return @csrs unless @csrs.nil?
178+
179+
@csrs = []
180+
extensions.each do |ext|
181+
ext_obj = @arch_def.extension(ext.name)
182+
ext_obj.csrs.each do |csr|
183+
@csrs << csr
184+
end
185+
end
186+
@csrs
187+
end
174188
end

0 commit comments

Comments
 (0)