Skip to content

Commit 3cd49fa

Browse files
authored
Make mstatus.SD/FS/VS dependent on parameters (#190)
* Make mstatus.SD/FS/VS dependent on parameters --------- Signed-off-by: Derek Hower <[email protected]>
1 parent e728581 commit 3cd49fa

File tree

11 files changed

+213
-19
lines changed

11 files changed

+213
-19
lines changed

.vscode/settings.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,5 @@
99
"files.watcherExclude": {
1010
"**/.home": true
1111
},
12-
"asciidoc.antora.enableAntoraSupport": true
12+
"asciidoc.antora.showEnableAntoraPrompt": true
1313
}

arch/csr/mstatus.yaml

Lines changed: 57 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,29 @@ mstatus:
2222
2323
Read-only bit that summarizes whether either the FS, XS, or VS
2424
fields signal the presence of some dirty state.
25-
type: RO-H
26-
reset_value: UNDEFINED_LEGAL
27-
affectedBy: [F, D, V]
25+
definedBy:
26+
anyOf: [F,V] # NOTE: if you implement a custom extension overlay that writes to XS, then you need to add your extension here in the overlay as well
27+
type(): |
28+
# this is read-only if FS and VS are both read-only
29+
# otherwise, it is read-only with hardware update
30+
31+
if (implemented?(ExtensionName::F) && (HW_MSTATUS_FS_DIRTY_UPDATE != "never")) {
32+
return CsrFieldType::ROH;
33+
} else if (implemented?(ExtensionName::V) && (HW_MSTATUS_VS_DIRTY_UPDATE != "never")) {
34+
return CsrFieldType::ROH;
35+
} else {
36+
return CsrFieldType::RO;
37+
}
38+
reset_value(): |
39+
# the reset value is known if both FS and VS are legal
40+
# make this a function call so that it can be displayed succinctly in docs
41+
42+
if (mstatus_sd_has_known_reset()) {
43+
return mstatus_sd_reset_value();
44+
} else {
45+
return UNDEFINED_LEGAL;
46+
}
47+
2848
MPV:
2949
location: 39
3050
base: 64
@@ -339,7 +359,8 @@ mstatus:
339359
# there will be no hardware update in this case because we know the F extension isn't implemented
340360
return MSTATUS_FS_WRITEABLE ? CsrFieldType::RW : CsrFieldType::RO;
341361
}
342-
definedBy: F
362+
definedBy:
363+
anyOf: [F, S]
343364
reset_value(): |
344365
if (CSR[misa].F == 1'b1){
345366
return UNDEFINED_LEGAL;
@@ -410,9 +431,38 @@ mstatus:
410431
When a vector register or vector CSR is written, VS obtains the value 3.
411432
Values 1 and 2 are valid write values for software, but are not interpreted by hardware
412433
other than to possibly enable a previously-disabled vector unit.
413-
type: RW-H
414-
reset_value: UNDEFINED_LEGAL
415-
definedBy: V
434+
definedBy:
435+
anyOf: [V, S]
436+
type(): |
437+
if (CSR[misa].V == 1'b1){
438+
return CsrFieldType::RWH;
439+
} else if ((CSR[misa].S == 1'b0) && (CSR[misa].V == 1'b0)) {
440+
# must be read-only-0
441+
return CsrFieldType::RO;
442+
} else {
443+
# there will be no hardware update in this case because we know the V extension isn't implemented
444+
return MSTATUS_VS_WRITEABLE ? CsrFieldType::RW : CsrFieldType::RO;
445+
}
446+
reset_value(): |
447+
if (CSR[misa].V == 1'b1){
448+
return UNDEFINED_LEGAL;
449+
} else if ((CSR[misa].S == 1'b0) && (CSR[misa].V == 1'b0)) {
450+
# must be read-only-0
451+
return 0;
452+
} else {
453+
# there will be no hardware update in this case because we know the V extension isn't implemented
454+
return MSTATUS_VS_WRITEABLE ? UNDEFINED_LEGAL : 0;
455+
}
456+
sw_write(csr_value): |
457+
if (CSR[misa].V == 1'b1){
458+
return ary_includes?<$array_size(MSTATUS_VS_LEGAL_VALUES), 2>(MSTATUS_VS_LEGAL_VALUES, csr_value.FS) ? csr_value.FS : UNDEFINED_LEGAL_DETERMINISTIC;
459+
} else if ((CSR[misa].S == 1'b0) && (CSR[misa].V == 1'b0)) {
460+
# must be read-only-0
461+
return 0;
462+
} else {
463+
# there will be no hardware update in this case because we know the V extension isn't implemented
464+
return ary_includes?<$array_size(MSTATUS_VS_LEGAL_VALUES), 2>(MSTATUS_VS_LEGAL_VALUES, csr_value.FS) ? csr_value.FS : UNDEFINED_LEGAL_DETERMINISTIC;
465+
}
416466
SPP:
417467
location: 8
418468
description: |

arch/ext/F.yaml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -246,13 +246,13 @@ F:
246246
Values are:
247247
[separator="!"]
248248
!===
249-
h! none ! Hardware never writes `mstatus.FS`
249+
h! never ! Hardware never writes `mstatus.FS`
250250
h! precise ! Hardware writes `mstatus.FS` to the Dirty (3) state precisely when F registers are modified
251251
h! imprecise ! Hardware writes `mstatus.FS` imprecisely. This will result in a call to unpredictable() on any attempt to read `mstatus` or write FP state.
252252
!===
253253
schema:
254254
type: string
255-
enum: ["none", "precise", "imprecise"]
255+
enum: ["never", "precise", "imprecise"]
256256
MSTATUS_FS_LEGAL_VALUES:
257257
description: |
258258
The set of values that mstatus.FS will accept from a software write.
@@ -268,4 +268,4 @@ F:
268268
assert MSTATUS_FS_LEGAL_VALUES.include?(0) && MSTATUS_FS_LEGAL_VALUES.include?(3) if ext?(:F)
269269
270270
# if HW is writing FS, then Dirty (3) better be a supported value
271-
assert MSTATUS_FS_LEGAL_VALUES.include?(3) if ext?(:F) && (HW_MSTATUS_FS_DIRTY_UPDATE != "none")
271+
assert MSTATUS_FS_LEGAL_VALUES.include?(3) if ext?(:F) && (HW_MSTATUS_FS_DIRTY_UPDATE != "never")

arch/ext/S.yaml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,15 @@ S:
254254
type: boolean
255255
extra_validation:
256256
assert MSTATUS_FS_WRITEABLE == true if ext?(:F)
257+
MSTATUS_VS_WRITEABLE:
258+
description: |
259+
When `S` is enabled but `V` is not, mstatus.VS is optionally writeable.
260+
261+
This parameter only has an effect when both S and V mode are disabled.
262+
schema:
263+
type: boolean
264+
extra_validation:
265+
assert MSTATUS_VS_WRITEABLE == true if ext?(:V)
257266
MSTATUS_FS_LEGAL_VALUES:
258267
description: |
259268
The set of values that mstatus.FS will accept from a software write.
@@ -267,6 +276,22 @@ S:
267276
also_defined_in: F
268277
extra_validation: |
269278
assert MSTATUS_FS_LEGAL_VALUES.include?(0) && MSTATUS_FS_LEGAL_VALUES.include?(3) if ext?(:F)
279+
MSTATUS_VS_LEGAL_VALUES:
280+
description: |
281+
The set of values that mstatus.VS will accept from a software write.
282+
schema:
283+
type: array
284+
items:
285+
type: integer
286+
enum: [0,1,2,3]
287+
maxItems: 4
288+
uniqueItems: true
289+
also_defined_in: V
290+
extra_validation: |
291+
assert MSTATUS_VS_LEGAL_VALUES.include?(0) && MSTATUS_VS_LEGAL_VALUES.include?(3) if ext?(:V)
292+
293+
# if HW is writing VS, then Dirty (3) better be a supported value
294+
assert MSTATUS_VS_LEGAL_VALUES.include?(3) if ext?(:V) && (HW_MSTATUS_VS_DIRTY_UPDATE != "never")
270295
MSTATUS_TVM_IMPLEMENTED:
271296
description: |
272297
Whether or not mstatus.TVM is implemented.

arch/ext/V.yaml

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,34 @@ V:
1414
description: |
1515
Indicates whether or not the `V` extension can be disabled with the `misa.V` bit.
1616
schema:
17-
type: boolean
17+
type: boolean
18+
HW_MSTATUS_VS_DIRTY_UPDATE:
19+
description: |
20+
Indicates whether or not hardware will write to `mstatus.VS`
21+
22+
Values are:
23+
[separator="!"]
24+
!===
25+
h! never ! Hardware never writes `mstatus.VS`
26+
h! precise ! Hardware writes `mstatus.VS` to the Dirty (3) state precisely when V registers are modified
27+
h! imprecise ! Hardware writes `mstatus.VS` imprecisely. This will result in a call to unpredictable() on any attempt to read `mstatus` or write vector state.
28+
!===
29+
schema:
30+
type: string
31+
enum: ["never", "precise", "imprecise"]
32+
MSTATUS_VS_LEGAL_VALUES:
33+
description: |
34+
The set of values that mstatus.VS will accept from a software write.
35+
schema:
36+
type: array
37+
items:
38+
type: integer
39+
enum: [0,1,2,3]
40+
maxItems: 4
41+
uniqueItems: true
42+
also_defined_in: S
43+
extra_validation: |
44+
assert MSTATUS_VS_LEGAL_VALUES.include?(0) && MSTATUS_VS_LEGAL_VALUES.include?(3) if ext?(:V)
45+
46+
# if HW is writing VS, then Dirty (3) better be a supported value
47+
assert MSTATUS_VS_LEGAL_VALUES.include?(3) if ext?(:V) && (HW_MSTATUS_VS_DIRTY_UPDATE != "never")

arch/isa/globals.isa

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2798,3 +2798,45 @@ function write_memory {
27982798
}
27992799
}
28002800

2801+
function mstatus_sd_has_known_reset
2802+
{
2803+
returns Boolean
2804+
description {
2805+
Returns true if the mstatus.SD bit has a defined reset value, as determined by various parameters.
2806+
}
2807+
body {
2808+
# the reset value is known if both FS and VS are known
2809+
2810+
Boolean fs_has_single_value =
2811+
((!implemented?(ExtensionName::F)) || ($array_size(MSTATUS_FS_LEGAL_VALUES) == 1));
2812+
2813+
Boolean vs_has_single_value =
2814+
((!implemented?(ExtensionName::V)) || ($array_size(MSTATUS_VS_LEGAL_VALUES) == 1));
2815+
2816+
return fs_has_single_value && vs_has_single_value;
2817+
}
2818+
}
2819+
2820+
function mstatus_sd_reset_value
2821+
{
2822+
returns Bits<1>
2823+
description {
2824+
Returns the reset value of mstatus.SD when known
2825+
}
2826+
body {
2827+
# the reset value is known if both FS and VS are known
2828+
assert(mstatus_sd_has_known_reset(),
2829+
"mstatus_sd_reset_value is only defined when mstatus_sd_has_known_reset() == true");
2830+
2831+
Bits<2> fs_value, vs_value; # defaults to 0
2832+
2833+
if ((!implemented?(ExtensionName::F)) || ($array_size(MSTATUS_FS_LEGAL_VALUES) == 1)) {
2834+
fs_value = (!implemented?(ExtensionName::F)) ? 0 : MSTATUS_FS_LEGAL_VALUES[0];
2835+
}
2836+
if ((!implemented?(ExtensionName::V)) || ($array_size(MSTATUS_VS_LEGAL_VALUES) == 1)) {
2837+
fs_value = (!implemented?(ExtensionName::V)) ? 0 : MSTATUS_VS_LEGAL_VALUES[0];
2838+
}
2839+
2840+
return ((fs_value == 3) || (vs_value == 3)) ? 1 : 0;
2841+
}
2842+
}

cfgs/generic_rv64/params.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -514,4 +514,7 @@ params:
514514
MSTATUS_FS_WRITEABLE: true
515515
MSTATUS_TVM_IMPLEMENTED: true
516516
HW_MSTATUS_FS_DIRTY_UPDATE: precise
517+
MSTATUS_VS_WRITEABLE: true
518+
MSTATUS_VS_LEGAL_VALUES: [0,1,2,3]
519+
HW_MSTATUS_VS_DIRTY_UPDATE: precise
517520
FORCE_UPGRADE_CBO_INVAL_TO_FLUSH: true

lib/idl/ast.rb

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,8 @@ def print_ast(indent = 0, indent_size: 2, io: $stdout)
361361

362362
# @!macro freeze_tree
363363
def freeze_tree(global_symtab)
364+
return if frozen?
365+
364366
@children.each { |child| child.freeze_tree(global_symtab) }
365367
freeze
366368
end
@@ -1095,6 +1097,8 @@ def initialize(input, interval, user_type)
10951097
end
10961098

10971099
def freeze_tree(global_symtab)
1100+
return if frozen?
1101+
10981102
# call type to get it set before we freeze the object
10991103
type(global_symtab)
11001104
freeze
@@ -1257,6 +1261,8 @@ def initialize(input, interval, name, size, fields)
12571261

12581262
# @!macro freeze_tree
12591263
def freeze_tree(global_symtab)
1264+
return if frozen?
1265+
12601266
type(global_symtab)
12611267
freeze
12621268
end
@@ -1498,7 +1504,9 @@ def type_check(symtab)
14981504
if var.type(symtab).kind == :array
14991505
value_result = value_try do
15001506
index_value = index.value(symtab)
1501-
type_error "Array index out of range" if index_value >= var.type(symtab).width
1507+
if var.type(symtab).width != :unknown
1508+
type_error "Array index out of range" if index_value >= var.type(symtab).width
1509+
end
15021510
end # Ok, doesn't need to be known
15031511

15041512
elsif var.type(symtab).integral?
@@ -2161,22 +2169,26 @@ def to_ast
21612169
class MultiVariableDeclarationAst < AstNode
21622170
include Declaration
21632171

2172+
# @return [AstNode] Declared type
21642173
def type_name = @children[0]
2165-
def var_names = @children[1..]
2174+
2175+
# @return [Array<AstNode>] Variable names
2176+
def var_name_nodes = @children[1..]
21662177

21672178
def initialize(input, interval, type_name, var_names)
21682179
super(input, interval, [type_name] + var_names)
21692180

21702181
@global = false
21712182
end
21722183

2184+
# mark this declaration as being in global scope
21732185
def make_global
21742186
@global = true
21752187
end
21762188

21772189
# @return [Array<String>] Variables being declared
21782190
def var_names
2179-
var_names.map(&:text_value)
2191+
var_name_nodes.map(&:text_value)
21802192
end
21812193

21822194
# @!macro type_check
@@ -2186,6 +2198,7 @@ def type_check(symtab)
21862198
add_symbol(symtab)
21872199
end
21882200

2201+
# @!macro type
21892202
def type(symtab)
21902203
if @global
21912204
type_name.type(symtab).clone.make_global
@@ -2196,13 +2209,13 @@ def type(symtab)
21962209

21972210
# @!macro add_symbol
21982211
def add_symbol(symtab)
2199-
var_names.each do |vname|
2200-
symtab.add(vname.text_values, Var.new(vname.text_value, type(symtab), type(symtab).default))
2212+
var_name_nodes.each do |vname|
2213+
symtab.add(vname.text_value, Var.new(vname.text_value, type(symtab), type(symtab).default))
22012214
end
22022215
end
22032216

22042217
# @!macro to_idl
2205-
def to_idl = "#{type_name.to_idl} #{var_names.map(&:to_idl).join(', ')}"
2218+
def to_idl = "#{type_name.to_idl} #{var_name_nodes.map(&:to_idl).join(', ')}"
22062219
end
22072220

22082221
class VariableDeclarationSyntaxNode < Treetop::Runtime::SyntaxNode
@@ -3415,6 +3428,8 @@ def initialize(input, interval, class_name, member_name)
34153428
34163429
# @!macro freeze_tree
34173430
def freeze_tree(global_symtab)
3431+
return if frozen?
3432+
34183433
enum_def_ast = global_symtab.archdef.global_ast.enums.find { |e| e.name == @enum_class_name }
34193434
34203435
@enum_def_type =
@@ -4179,6 +4194,8 @@ def type_check(symtab)
41794194
end
41804195
41814196
def freeze_tree(symtab)
4197+
return if frozen?
4198+
41824199
if @type_name == "Bits"
41834200
# precalculate size if possible
41844201
begin
@@ -4849,6 +4866,8 @@ def initialize(input, interval, name, targs, return_types, arguments, desc, body
48494866
48504867
# @!macro freeze_tree
48514868
def freeze_tree(global_symtab)
4869+
return if frozen?
4870+
48524871
unless templated?
48534872
arguments(global_symtab)
48544873
end
@@ -5679,6 +5698,8 @@ def initialize(input, interval, idx, field_name)
56795698
end
56805699
56815700
def freeze_tree(symtab)
5701+
return if frozen?
5702+
56825703
value_result = value_try do
56835704
@value = calc_value(symtab)
56845705
end
@@ -5819,6 +5840,8 @@ def initialize(input, interval, idx)
58195840
end
58205841
58215842
def freeze_tree(symtab)
5843+
return if frozen?
5844+
58225845
@archdef = symtab.archdef # remember archdef, used by gen_adoc pass
58235846
@idx.freeze_tree(symtab)
58245847
freeze

lib/idl/passes/gen_adoc.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,12 @@ def gen_adoc(indent = 0, indent_spaces: 2)
159159
end
160160
end
161161

162+
class MultiVariableDeclarationAst
163+
def gen_adoc(indent = 0, indent_spaces: 2)
164+
"#{' ' * indent}#{type_name.gen_adoc(0, indent_spaces:)} #{var_name_nodes.map { |var| var.gen_adoc(0, indent_spaces:) }.join(', ')}"
165+
end
166+
end
167+
162168
class TernaryOperatorExpressionAst
163169
def gen_adoc(indent = 0, indent_spaces: 2)
164170
"#{' ' * indent}#{condition.gen_adoc(0, indent_spaces:)} ? #{true_expression.gen_adoc(0, indent_spaces:)} : #{false_expression.gen_adoc(0, indent_spaces:)}"

0 commit comments

Comments
 (0)