Skip to content

Commit 13da20c

Browse files
author
Derek Hower
committed
Add list of extension parameters to manual
1 parent 5bd88a0 commit 13da20c

File tree

13 files changed

+132
-65
lines changed

13 files changed

+132
-65
lines changed

arch/ext/Sm.yaml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -415,9 +415,8 @@ Sm:
415415
TODO: GitHub issue 53
416416
schema:
417417
type: integer
418-
# GitHub issue 53
419-
# when:
420-
# version: ">= 1.12.0"
418+
when:
419+
version: ">= 1.12.0"
421420
PMA_GRANULARITY:
422421
description: |
423422
log2 of the smallest supported PMA region.

backends/manual/tasks.rake

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,24 @@ rule %r{#{MANUAL_GEN_DIR}/.*/.*/antora/modules/funcs/pages/funcs.adoc} => [
241241
File.write t.name, AntoraUtils.resolve_links(arch_def.find_replace_links(erb.result(binding)))
242242
end
243243

244+
# rule to create IDL function appendix page
245+
rule %r{#{MANUAL_GEN_DIR}/.*/.*/antora/modules/params/pages/param_list.adoc} => [
246+
__FILE__,
247+
"#{$root}/.stamps/arch-gen-_64.stamp",
248+
($root / "backends" / "manual" / "templates" / "param_list.adoc.erb").to_s
249+
] do |t|
250+
arch_def = arch_def_for("_64")
251+
parts = t.name.sub("#{MANUAL_GEN_DIR}/", "").split("/")
252+
manual_version = arch_def.manual(parts[0])&.version(parts[1])
253+
254+
param_list_template_path = $root / "backends" / "manual" / "templates" / "param_list.adoc.erb"
255+
erb = ERB.new(param_list_template_path.read, trim_mode: "-")
256+
erb.filename = param_list_template_path.to_s
257+
258+
FileUtils.mkdir_p File.dirname(t.name)
259+
File.write t.name, AntoraUtils.resolve_links(arch_def.find_replace_links(erb.result(binding)))
260+
end
261+
244262
rule %r{#{MANUAL_GEN_DIR}/.*/top/.*/antora/landing/antora.yml} => [
245263
__FILE__
246264
] do |t|
@@ -394,6 +412,7 @@ namespace :gen do
394412
version.extensions.each do |ext|
395413
Rake::Task[antora_path / "modules" / "exts" / "pages" / "#{ext.name}.adoc"].invoke
396414
end
415+
Rake::Task[antora_path / "modules" / "params" / "pages" / "param_list.adoc"].invoke
397416
end
398417

399418
landing_page_path = MANUAL_GEN_DIR / ENV["MANUAL_NAME"] / "top" / output_hash / "antora" / "landing" / "modules" / "ROOT" / "pages" / "index.adoc"
Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,26 @@
11
<%- manual_version.volumes.each do |volume| -%>
2-
.<%= volume.title %>
2+
* <%= volume.title %>
33
<%- volume.chapters.each do |chapter| -%>
4-
* xref:chapters:<%= File.basename(chapter.path) %>[<%= chapter.title %>]
4+
** xref:chapters:<%= File.basename(chapter.path) %>[<%= chapter.title %>]
55
<%- end -%>
66

77
<%- end -%>
88

9-
.Alphabetical list of instrutions
9+
* Alphabetical list of instrutions
1010
<%- manual_version.instructions.sort { |a, b| a.name <=> b.name }.each do |inst| -%>
11-
* xref:insts:<%= inst.name %>.adoc[<%= inst.name %>]
11+
** xref:insts:<%= inst.name %>.adoc[<%= inst.name %>]
1212
<%- end -%>
1313

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

19-
.Alphabetical list of extensions
19+
* Alphabetical list of extensions
2020
<%- manual_version.extensions.sort { |a, b| a.name <=> b.name }.each do |ext| -%>
21-
* xref:exts:<%= ext.name %>.adoc[<%= ext.name %>]
21+
** xref:exts:<%= ext.name %>.adoc[<%= ext.name %>]
2222
<%- end -%>
2323

24-
.Execution functions (IDL)
25-
* xref:funcs:funcs.adoc[Functions]
24+
* xref:params:param_list.adoc[Alphabetical list of parameters]
25+
26+
* xref:funcs:funcs.adoc[Execution functions (IDL)]
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
= Architectural Parameters
2+
3+
<%-
4+
params = manual_version.extensions.map{ |e| e.params(arch_def) }.flatten.uniq(&:name).sort_by!(&:name)
5+
-%>
6+
7+
The following <%= params.size %> parameters are defined in this manual:
8+
9+
|===
10+
| Name | Type | Extension(s) | Description
11+
12+
<%- params.each do |param| -%>
13+
| <%= param.name %>
14+
| <%= param.schema.to_pretty_s %>
15+
| <%= param.exts.map { |ext| "`#{ext.name}`"}.join(", ") %>
16+
a| <%= param.desc %>
17+
<%- end -%>
18+
|===

lib/arch_def.rb

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -432,15 +432,11 @@ def conflicting_ext?(ext_name)
432432
prohibited_extensions.include? { |ext_req| ext_req.name == ext_name }
433433
end
434434

435-
# @return [Array<ExtensionParameter>] List of all parameters defined in the architecture
435+
# @return [Array<ExtensionParameter>] Alphabetical list of all parameters defined in the architecture
436436
def params
437437
return @params unless @params.nil?
438438

439-
@params = []
440-
extensions.each do |ext|
441-
@params += ext.params
442-
end
443-
@params
439+
@params = extensions.map(&:params).flatten.uniq(&:name).sort_by!(&:name)
444440
end
445441

446442
# @return [Hash<String, ExtensionParameter>] Hash of all extension parameters defined in the architecture

lib/arch_obj_models/crd.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ def allowed_values
234234
end
235235

236236
# Create a Schema object just using information in the parameter database.
237-
schema_obj = Schema.new(@param_db.schema)
237+
schema_obj = @param_db.schema
238238

239239
# Merge in constraints imposed by the CRD on the parameter.
240240
schema_obj.merge!(@schema_crd)

lib/arch_obj_models/extension.rb

Lines changed: 43 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,16 @@
55

66
# A parameter (AKA option, AKA implementation-defined value) supported by an extension
77
class ExtensionParameter
8+
# @return [ArchDef] The defining Arch def
9+
attr_reader :archdef
10+
811
# @return [String] Parameter name
912
attr_reader :name
1013

1114
# @return [String] Asciidoc description
1215
attr_reader :desc
1316

14-
# @return [Hash] JSON Schema for the parameter value
17+
# @return [Schema] JSON Schema for this param
1518
attr_reader :schema
1619

1720
# @return [String] Ruby code to perform validation above and beyond JSON schema
@@ -25,25 +28,46 @@ class ExtensionParameter
2528
attr_reader :exts
2629

2730
# @returns [Idl::Type] Type of the parameter
28-
attr_reader :type
31+
attr_reader :idl_type
2932

3033
# Pretty convert extension schema to a string.
3134
def schema_type
32-
Schema.new(@schema).to_pretty_s
35+
@schema.to_pretty_s
3336
end
3437

35-
def initialize(name, desc, schema, extra_validation, exts)
38+
def initialize(ext, name, data)
39+
@archdef = ext.arch_def
40+
@data = data
3641
@name = name
37-
@desc = desc
38-
@schema = schema
39-
@extra_validation = extra_validation
40-
@exts = exts
41-
begin
42-
@type = Idl::Type.from_json_schema(@schema).make_const.freeze
43-
rescue
44-
warn "While parsing scheme for ExtensionParameter #{ext.name}.#{name}"
45-
raise
42+
@desc = data["description"]
43+
@schema = Schema.new(data["schema"])
44+
@extra_validation = data["extra_validation"]
45+
also_defined_in = []
46+
unless data["also_defined_in"].nil?
47+
if data["also_defined_in"].is_a?(String)
48+
other_ext = @archdef.extension(data["also_defined_in"])
49+
raise "Definition error in #{ext.name}.#{name}: #{data['also_defined_in']} is not a known extension" if other_ext.nil?
50+
also_defined_in << other_ext
51+
else
52+
unless data["also_defined_in"].is_a?(Array) && data["also_defined_in"].all? { |e| e.is_a?(String) }
53+
raise "schema error: also_defined_in should be a string or array of strings"
54+
end
55+
56+
data["also_defined_in"].each do |other_ext_name|
57+
other_ext = @archdef.extension(other_ext_name)
58+
raise "Definition error in #{ext.name}.#{name}: #{data['also_defined_in']} is not a known extension" if other_ext.nil?
59+
also_defined_in << other_ext
60+
end
61+
end
4662
end
63+
@exts = [ext] + also_defined_in
64+
@idl_type = @schema.to_idl_type.make_const.freeze
65+
end
66+
67+
def defined_in_extension_version?(version)
68+
return true if @data.dig("when", "version").nil?
69+
70+
Gem::Requirement.new(@data["when"]["version"]).satisfied_by?(version)
4771
end
4872

4973
# sorts by name
@@ -135,31 +159,7 @@ def params
135159
@params = []
136160
if @data.key?("params")
137161
@data["params"].each do |param_name, param_data|
138-
also_defined_in = []
139-
unless param_data["also_defined_in"].nil?
140-
if param_data["also_defined_in"].is_a?(String)
141-
other_ext = arch_def.extension(param_data["also_defined_in"])
142-
raise "Definition error in #{name}.#{param_name}: #{param_data['also_defined_in']} is not a known extension" if other_ext.nil?
143-
also_defined_in << other_ext
144-
else
145-
unless param_data["also_defined_in"].is_a?(Array) && param_data["also_defined_in"].all? { |e| e.is_a?(String) }
146-
raise "schema error: also_defined_in should be a string or array of strings"
147-
end
148-
149-
param_data["also_defined_in"].each do |other_ext_name|
150-
other_ext = arch_def.extension(other_ext_name)
151-
raise "Definition error in #{name}.#{param_name}: #{param_data['also_defined_in']} is not a known extension" if other_ext.nil?
152-
also_defined_in << other_ext
153-
end
154-
end
155-
end
156-
@params << ExtensionParameter.new(
157-
param_name,
158-
param_data["description"],
159-
param_data["schema"],
160-
param_data["extra_validation"],
161-
[self] + also_defined_in
162-
)
162+
@params << ExtensionParameter.new(self, param_name, param_data)
163163
end
164164
end
165165
@params
@@ -277,6 +277,11 @@ def ext(arch_def)
277277
arch_def.extension(name)
278278
end
279279

280+
# @return [Array<ExtensionParameter>] The list of parameters for this extension version
281+
def params(arch_def)
282+
ext(arch_def).params.select { |p| p.defined_in_extension_version?(@version) }
283+
end
284+
280285
# @overload ==(other)
281286
# @param other [String] An extension name
282287
# @return [Boolean] whether or not this ExtensionVersion is named 'other'

lib/arch_obj_models/manual.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ def volumes
152152

153153
def state = @data["state"]
154154

155+
# @return [Array<ExtensionVersion>] Array of extension versions in this manual version
155156
def extensions
156157
return @extensions unless @extensions.nil?
157158

lib/arch_obj_models/schema.rb

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,22 @@
11
#frozen_string_literal: true
22

3+
require_relative "../idl/type"
4+
5+
# represents a JSON Schema
6+
#
7+
# Used when an object in the database specifies a constraint using JSON schema
8+
# For example, extension parameters
39
class Schema
410
def initialize(schema_hash)
511
raise ArgumentError, "Expecting hash" unless schema_hash.is_a?(Hash)
612

713
@schema_hash = schema_hash
814
end
915

16+
# @return [Hash] Hash representation of the JSON Schema
17+
def to_h = @schema_hash
18+
19+
# @return [String] A human-readable description of the schema
1020
def to_pretty_s(schema_hash = @schema_hash)
1121
raise ArgumentError, "Expecting hash" unless schema_hash.is_a?(Hash)
1222
raise ArgumentError, "Expecting non-empty hash" if schema_hash.empty?
@@ -138,5 +148,10 @@ def num_bits(min, max)
138148
return 0 unless min == 0
139149
is_power_of_two?(max+1) ? max.bit_length : 0
140150
end
151+
152+
# @return [Idl::Type] THe IDL-equivalent type for this schema object
153+
def to_idl_type
154+
Idl::Type.from_json_schema(@schema_hash)
155+
end
141156
end
142157

lib/idl/symbol_table.rb

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -138,17 +138,17 @@ def initialize(arch_def, effective_xlen = nil)
138138
if param.exts.size == 1
139139
if param.name == "XLEN"
140140
# special case: we actually do know XLEN
141-
add!(param.name, Var.new(param.name, param.type.clone.make_const, @mxlen))
141+
add!(param.name, Var.new(param.name, param.idl_type.clone.make_const, @mxlen))
142142
else
143-
add!(param.name, Var.new(param.name, param.type.clone.make_const))
143+
add!(param.name, Var.new(param.name, param.idl_type.clone.make_const))
144144
end
145145
else
146146
# could already be present...
147147
existing_sym = get(param.name)
148148
if existing_sym.nil?
149-
add!(param.name, Var.new(param.name, param.type.clone.make_const))
149+
add!(param.name, Var.new(param.name, param.idl_type.clone.make_const))
150150
else
151-
unless existing_sym.type.equal_to?(param.type)
151+
unless existing_sym.type.equal_to?(param.idl_type)
152152
raise "Definition error: Param #{param.name} is defined by multiple extensions and is not the same definition in each"
153153
end
154154
end

0 commit comments

Comments
 (0)