Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add CSR list to manual #29

Merged
merged 1 commit into from
Sep 20, 2024
Merged
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
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
Loading