Skip to content

Commit

Permalink
Add CSR list to manual
Browse files Browse the repository at this point in the history
  • Loading branch information
dhower-qc committed Sep 20, 2024
1 parent fbe6a41 commit 6580857
Show file tree
Hide file tree
Showing 9 changed files with 258 additions and 12 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/pages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,12 @@ jobs:
run: ./bin/build_container
- name: Setup project
run: ./bin/setup
- name: Build manual
run: ./do gen:html_manual MANUAL_NAME=isa VERSIONS=all
- name: Build html documentation for generic_rv64
run: ./do gen:html[generic_rv64]
- name: Generate YARD docs
run: ./do gen:tool_doc
- name: Build manual
run: ./do gen:html_manual MANUAL_NAME=isa VERSIONS=all
- name: Create _site/example_cfg
run: mkdir -p _site/example_cfg
- name: Create _site/manual
Expand Down
42 changes: 41 additions & 1 deletion arch/manual/isa/20240411/contents.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ volumes:
#/End of Vector appendices
extensions:
- [I, "2.1.0"]
- [U, "1.12.0"]
# - [E, "2.0"]
# - [RVI64, "2.1"]
# - [RVI128, "1.7"]
Expand Down Expand Up @@ -176,4 +177,43 @@ volumes:
- name: Andrew Waterman
email: [email protected]
organization: SiFive, Inc.
url: https://www.sifive.com/
url: https://www.sifive.com/
chapters:
- riscv-isa-manual/src/priv-preface.adoc
- riscv-isa-manual/src/priv-intro.adoc
- riscv-isa-manual/src/priv-csrs.adoc
- riscv-isa-manual/src/machine.adoc
- riscv-isa-manual/src/smstateen.adoc
- riscv-isa-manual/src/indirect-csr.adoc
- riscv-isa-manual/src/smepmp.adoc
- riscv-isa-manual/src/smcntrpmf.adoc
- riscv-isa-manual/src/rnmi.adoc
- riscv-isa-manual/src/smcdeleg.adoc
- riscv-isa-manual/src/supervisor.adoc
- riscv-isa-manual/src/sstc.adoc
- riscv-isa-manual/src/sscofpmf.adoc
- riscv-isa-manual/src/hypervisor.adoc
- riscv-isa-manual/src/priv-insns.adoc
- riscv-isa-manual/src/priv-history.adoc
- riscv-isa-manual/src/bibliography.adoc
extensions:
- [Smstateen, "1.0.0"]
- [Smcsrind, "1.0.0"]
- [Sscsrind, "1.0.0"]
- [Smepmp, "1.0.0"]
- [Smcntrpmf, "1.0.0"]
- [Smrnmi, "0.5.0"]
- [Smcdeleg, "1.0.0"]
- [S, "1.12.0"]
- [Sv32, "1.13.0"]
- [Sv39, "1.13.0"]
- [Sv48, "1.13.0"]
- [Sv57, "1.13.0"]
- [Svnapot, "1.0.0"]
- [Svpbmt, "1.0.0"]
- [Svinval, "1.0.0"]
- [Svadu, "1.0.0"]
- [Svvptc, "1.0.0"]
- [Sstc, "1.0.0"]
- [Sscofpmf, "1.0.0"]
- [H, "1.0.0"]
25 changes: 24 additions & 1 deletion backends/manual/tasks.rake
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,26 @@ rule %r{#{MANUAL_GEN_DIR}/.*/.*/antora/modules/insts/pages/.*.adoc} => [
File.write t.name, AntoraUtils.resolve_links(erb.result(binding))
end

# rule to create csr appendix page
rule %r{#{MANUAL_GEN_DIR}/.*/.*/antora/modules/csrs/pages/.*.adoc} => [
__FILE__,
"gen:arch",
($root / "backends" / "manual" / "templates" / "csr.adoc.erb").to_s
] do |t|
csr_name = File.basename(t.name, ".adoc")

arch_def = arch_def_for("_")
csr = arch_def.csr(csr_name)
raise "Can't find csr '#{csr_name}'" if csr.nil?

csr_template_path = $root / "backends" / "manual" / "templates" / "csr.adoc.erb"
erb = ERB.new(csr_template_path.read, trim_mode: "-")
erb.filename = csr_template_path.to_s

FileUtils.mkdir_p File.dirname(t.name)
File.write t.name, AntoraUtils.resolve_links(erb.result(binding))
end

# rule to create IDL function appendix page
rule %r{#{MANUAL_GEN_DIR}/.*/.*/antora/modules/funcs/pages/funcs.adoc} => [
__FILE__,
Expand Down Expand Up @@ -274,7 +294,7 @@ rule %r{#{MANUAL_GEN_DIR}/.*/top/.*/antora/playbook.yml} => proc { |tname|
File.write t.name, erb.result(binding)
end

file $root / "ext" / "riscv-isa_manual" / "README.md" do
file $root / "ext" / "riscv-isa-manual" / "README.md" do
sh "git submodule update --init ext/riscv-isa-manual"
end

Expand Down Expand Up @@ -345,6 +365,9 @@ namespace :gen do
version.instructions.each do |inst|
Rake::Task[antora_path / "modules" / "insts" / "pages" / "#{inst.name}.adoc"].invoke
end
version.csrs.each do |csr|
Rake::Task[antora_path / "modules" / "csrs" / "pages" / "#{csr.name}.adoc"].invoke
end
end

playbook_path = MANUAL_GEN_DIR / ENV["MANUAL_NAME"] / "top" / output_hash / "antora" / "playbook.yml"
Expand Down
125 changes: 125 additions & 0 deletions backends/manual/templates/csr.adoc.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
:tabs-sync-option:

[#csrs-<%= csr.name.gsub('.', '_') %>,reftext=<%= csr.name %>]
= <%= csr.name %>

*<%= csr.long_name %>*

<%= csr.description %>

== Attributes
[%autowidth]
|===
h| CSR Address | <%= "0x#{csr.address.to_s(16)}" %>
<%- if csr.priv_mode == 'VS' -%>
h| Virtual CSR Address | <%= "0x#{csr.virtual_address.to_s(16)}" %>
<%- end -%>
<%- if csr.dynamic_length?(arch_def) -%>
h| Length | <%= csr.length_pretty(arch_def) %>
<%- else -%>
h| Length | <%= csr.length_pretty(arch_def) %>-bit
<%- end -%>
h| Privilege Mode | <%= csr.priv_mode %>
|===

== Format
<%- unless csr.dynamic_length?(arch_def) || csr.fields.any? { |f| f.dynamic_location?(arch_def) } -%>
<%# CSR has a known static length, so there is only one format to display -%>
.<%= csr.name %> format
[wavedrom, ,svg,subs='attributes',width="100%"]
....
<%= JSON.dump csr.wavedrom_desc(arch_def, 64) %>
....
<%- else -%>
<%# CSR has a dynamic length, or a field has a dynamic location,
so there is more than one format to display -%>
This CSR format changes dynamically.

.<%= csr.name %> Format when <%= csr.length_cond32 %>
[wavedrom, ,svg,subs='attributes',width="100%"]
....
<%= JSON.dump csr.wavedrom_desc(arch_def, 32) %>
....

.<%= csr.name %> Format when <%= csr.length_cond64 %>
[wavedrom, ,svg,subs='attributes',width="100%"]
....
<%= JSON.dump csr.wavedrom_desc(arch_def, 64) %>
....
<%- end -%>

== Field Summary

[%autowidth,float="center",align="center",cols="^,<,<,<",options="header",role="stretch"]
|===
|Name | Location | Type | Reset Value

<%- csr.fields.each do |field| -%>
| xref:<%=csr.name%>-<%=field.name%>-def[`<%= field.name %>`]
| <%= field.location_pretty(arch_def) %>
| <%= field.type_pretty(arch_def) %>
| <%= field.reset_value_pretty(arch_def) %>

<%- end -%>
|===

== Fields

<%- if csr.fields.empty? -%>
This CSR has no fields. However, it must still exist (not cause an `Illegal Instruction` trap) and always return zero on a read.
<%- else -%>

<%- csr.fields.each do |field| -%>
[[<%=csr.name%>-<%=field.name%>-def]]
=== `<%= field.name %>`

[example]
****
Location::
<%= field.location_pretty(arch_def) %>

Description::
<%= field.description %>

Type::
<%= field.type_pretty(arch_def) %>

Reset value::
<%= field.reset_value_pretty(arch_def) %>

****

<%- end -%>
<%- end -%>

<%- if csr.fields.map(&:has_custom_sw_write?).any? -%>
== Software write

This CSR may store a value that is different from what software attempts to write.

When a software write occurs (_e.g._, through `csrrw`), the following determines the
written value:

[idl]
----
<%- csr.fields.each do |field| -%>
<%- if field.has_custom_sw_write? -%>
<%= field.name %> = <%= field["sw_write(csr_value)"] %>
<%- else -%>
<%= field.name %> = csr_value.<%= field.name %>
<%- end -%>
<%- end -%>
----
<%- end -%>

<%- if csr.has_custom_sw_read? -%>
== Software read

This CSR may return a value that is different from what is stored in hardware.

[source,idl,subs="specialchars,macros"]
----
<%= csr.sw_read_ast(arch_def.idl_compiler).gen_adoc %>
----
<%- end -%>

1 change: 0 additions & 1 deletion backends/manual/templates/instruction.adoc.erb
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,6 @@ RV64::
----
<%= inst.operation_ast(inst.arch_def.idl_compiler).gen_adoc %>
----
====
<%- end -%>

<%# exception_list = inst.reachable_exceptions_str(inst.arch_def.sym_table_64, 64) -%>
Expand Down
5 changes: 5 additions & 0 deletions backends/manual/templates/isa_nav.adoc.erb
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,10 @@
* xref:insts:<%= inst.name %>.adoc[<%= inst.name %>]
<%- end -%>

.Alphabetical list of CSRs
<%- manual_version.csrs.sort { |a, b| a.name <=> b.name }.each do |csr| -%>
* xref:csrs:<%= csr.name %>.adoc[<%= csr.name %>]
<%- end -%>

.Execution functions (IDL)
* xref:funcs:funcs.adoc[Functions]
30 changes: 28 additions & 2 deletions lib/arch_obj_models/csr.rb
Original file line number Diff line number Diff line change
Expand Up @@ -154,9 +154,35 @@ def dynamic_length?(arch_def)
# !@data["length"].is_a?(Integer) && (@data["length"] != "MXLEN")
end

# @param arch_def [ArchDef] Architecture definition
# @return [Integer] Smallest length of the CSR in any mode
def min_length(arch_def)
case @data["length"]
when "MXLEN", "SXLEN", "VSXLEN"
32
when Integer
@data["length"]
else
raise "Unexpected length"
end
end

# @param arch_def [ArchDef] Architecture definition
# @return [Integer] Largest length of the CSR in any mode
def max_length(arch_def)
case @data["length"]
when "MXLEN", "SXLEN", "VSXLEN"
64
when Integer
@data["length"]
else
raise "Unexpected length"
end
end

# @param arch_def [ArchDef] A configuration (can be nil if the lenth is not dependent on a config parameter)
# @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
# @return [Integer] Length, in bits, of the CSR
# @return [Integer] Length, in bits, of the CSR, given effective_xlen
def length(arch_def, effective_xlen = nil)
case @data["length"]
when "MXLEN"
Expand All @@ -167,7 +193,7 @@ def length(arch_def, effective_xlen = nil)
@data["base"]
else
# don't know MXLEN
raise ArgumentError, "effective_xlen is required when length is MXLEN and arch_def is generic" if effective_xlen.nil?
raise ArgumentError, "for CSR #{name}: effective_xlen is required when length is MXLEN and arch_def is generic" if effective_xlen.nil?

effective_xlen
end
Expand Down
24 changes: 19 additions & 5 deletions lib/arch_obj_models/csr_field.rb
Original file line number Diff line number Diff line change
Expand Up @@ -532,17 +532,29 @@ def location(arch_def, effective_xlen = nil)
raise "Missing location for #{csr.name}.#{name} (#{key})?" unless @data.key?(key)

if @data[key].is_a?(Integer)
if @data[key] > csr.length(arch_def, effective_xlen || @data["base"])
raise "Location (#{key} = #{@data[key]}) is past the csr length (#{csr.length(arch_def, effective_xlen)}) in #{csr.name}.#{name}"
if (arch_def.is_a?(ImplArchDef))
if @data[key] > csr.length(arch_def, effective_xlen || @data["base"])
raise "Location (#{key} = #{@data[key]}) is past the csr length (#{csr.length(arch_def, effective_xlen)}) in #{csr.name}.#{name}"
end
else
if @data[key] > csr.max_length(arch_def)
raise "Location (#{key} = #{@data[key]}) is past the max csr length (#{csr.max_length(arch_def)}) in #{csr.name}.#{name}"
end
end

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

if e > csr.length(arch_def, effective_xlen)
raise "Location (#{key} = #{@data[key]}) is past the csr length (#{csr.length(arch_def, effective_xlen)}) in #{csr.name}.#{name}"
if (arch_def.is_a?(ImplArchDef))
if e > csr.length(arch_def, effective_xlen)
raise "Location (#{key} = #{@data[key]}) is past the csr length (#{csr.length(arch_def, effective_xlen)}) in #{csr.name}.#{name}"
end
else
if e > csr.max_length(arch_def)
raise "Location (#{key} = #{@data[key]}) is past the max csr length (#{csr.max_length(arch_def)}) in #{csr.name}.#{name}"
end
end

s..e
Expand Down Expand Up @@ -578,12 +590,14 @@ def location_pretty(arch_def)
if dynamic_location?(arch_def)
condition =
case csr.priv_mode
when "M"
"CSR[misa].MXL == %%"
when "S"
"CSR[mstatus].SXL == %%"
when "VS"
"CSR[hstatus].VSXL == %%"
else
raise "Unexpected priv mode"
raise "Unexpected priv mode #{csr.priv_mode} for #{csr.name}"
end

<<~LOC
Expand Down
14 changes: 14 additions & 0 deletions lib/arch_obj_models/manual.rb
Original file line number Diff line number Diff line change
Expand Up @@ -171,4 +171,18 @@ def instructions
end
@instructions
end

# @return [Array<Csr>] All csrs defined in this version
def csrs
return @csrs unless @csrs.nil?

@csrs = []
extensions.each do |ext|
ext_obj = @arch_def.extension(ext.name)
ext_obj.csrs.each do |csr|
@csrs << csr
end
end
@csrs
end
end

0 comments on commit 6580857

Please sign in to comment.