Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
2 changes: 1 addition & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@
"files.watcherExclude": {
"**/.home": true
},
"asciidoc.antora.enableAntoraSupport": true
"asciidoc.antora.showEnableAntoraPrompt": true
}
64 changes: 57 additions & 7 deletions arch/csr/mstatus.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,29 @@ mstatus:

Read-only bit that summarizes whether either the FS, XS, or VS
fields signal the presence of some dirty state.
type: RO-H
reset_value: UNDEFINED_LEGAL
affectedBy: [F, D, V]
definedBy:
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
type(): |
# this is read-only if FS and VS are both read-only
# otherwise, it is read-only with hardware update

if (implemented?(ExtensionName::F) && (HW_MSTATUS_FS_DIRTY_UPDATE != "never")) {
return CsrFieldType::ROH;
} else if (implemented?(ExtensionName::V) && (HW_MSTATUS_VS_DIRTY_UPDATE != "never")) {
return CsrFieldType::ROH;
} else {
return CsrFieldType::RO;
}
reset_value(): |
# the reset value is known if both FS and VS are legal
# make this a function call so that it can be displayed succinctly in docs

if (mstatus_sd_has_known_reset()) {
return mstatus_sd_reset_value();
} else {
return UNDEFINED_LEGAL;
}

MPV:
location: 39
base: 64
Expand Down Expand Up @@ -339,7 +359,8 @@ mstatus:
# there will be no hardware update in this case because we know the F extension isn't implemented
return MSTATUS_FS_WRITEABLE ? CsrFieldType::RW : CsrFieldType::RO;
}
definedBy: F
definedBy:
anyOf: [F, S]
reset_value(): |
if (CSR[misa].F == 1'b1){
return UNDEFINED_LEGAL;
Expand Down Expand Up @@ -410,9 +431,38 @@ mstatus:
When a vector register or vector CSR is written, VS obtains the value 3.
Values 1 and 2 are valid write values for software, but are not interpreted by hardware
other than to possibly enable a previously-disabled vector unit.
type: RW-H
reset_value: UNDEFINED_LEGAL
definedBy: V
definedBy:
anyOf: [V, S]
type(): |
if (CSR[misa].V == 1'b1){
return CsrFieldType::RWH;
} else if ((CSR[misa].S == 1'b0) && (CSR[misa].V == 1'b0)) {
# must be read-only-0
return CsrFieldType::RO;
} else {
# there will be no hardware update in this case because we know the V extension isn't implemented
return MSTATUS_VS_WRITEABLE ? CsrFieldType::RW : CsrFieldType::RO;
}
reset_value(): |
if (CSR[misa].V == 1'b1){
return UNDEFINED_LEGAL;
} else if ((CSR[misa].S == 1'b0) && (CSR[misa].V == 1'b0)) {
# must be read-only-0
return 0;
} else {
# there will be no hardware update in this case because we know the V extension isn't implemented
return MSTATUS_VS_WRITEABLE ? UNDEFINED_LEGAL : 0;
}
sw_write(csr_value): |
if (CSR[misa]. =V= 1'b1){
return ary_includes?<$array_size(MSTATUS_VS_LEGAL_VALUES), 2>(MSTATUS_VS_LEGAL_VALUES, csr_value.FS) ? csr_value.FS : UNDEFINED_LEGAL_DETERMINISTIC;
} else if ((CSR[misa].S == 1'b0) && (CSR[misa].V == 1'b0)) {
# must be read-only-0
return 0;
} else {
# there will be no hardware update in this case because we know the V extension isn't implemented
return ary_includes?<$array_size(MSTATUS_VS_LEGAL_VALUES), 2>(MSTATUS_VS_LEGAL_VALUES, csr_value.FS) ? csr_value.FS : UNDEFINED_LEGAL_DETERMINISTIC;
}
SPP:
location: 8
description: |
Expand Down
6 changes: 3 additions & 3 deletions arch/ext/F.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -246,13 +246,13 @@ F:
Values are:
[separator="!"]
!===
h! none ! Hardware never writes `mstatus.FS`
h! never ! Hardware never writes `mstatus.FS`
h! precise ! Hardware writes `mstatus.FS` to the Dirty (3) state precisely when F registers are modified
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.
!===
schema:
type: string
enum: ["none", "precise", "imprecise"]
enum: ["never", "precise", "imprecise"]
MSTATUS_FS_LEGAL_VALUES:
description: |
The set of values that mstatus.FS will accept from a software write.
Expand All @@ -268,4 +268,4 @@ F:
assert MSTATUS_FS_LEGAL_VALUES.include?(0) && MSTATUS_FS_LEGAL_VALUES.include?(3) if ext?(:F)

# if HW is writing FS, then Dirty (3) better be a supported value
assert MSTATUS_FS_LEGAL_VALUES.include?(3) if ext?(:F) && (HW_MSTATUS_FS_DIRTY_UPDATE != "none")
assert MSTATUS_FS_LEGAL_VALUES.include?(3) if ext?(:F) && (HW_MSTATUS_FS_DIRTY_UPDATE != "never")
25 changes: 25 additions & 0 deletions arch/ext/S.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,15 @@ S:
type: boolean
extra_validation:
assert MSTATUS_FS_WRITEABLE == true if ext?(:F)
MSTATUS_VS_WRITEABLE:
description: |
When `S` is enabled but `V` is not, mstatus.VS is optionally writeable.

This parameter only has an effect when both S and V mode are disabled.
schema:
type: boolean
extra_validation:
assert MSTATUS_VS_WRITEABLE == true if ext?(:V)
MSTATUS_FS_LEGAL_VALUES:
description: |
The set of values that mstatus.FS will accept from a software write.
Expand All @@ -267,6 +276,22 @@ S:
also_defined_in: F
extra_validation: |
assert MSTATUS_FS_LEGAL_VALUES.include?(0) && MSTATUS_FS_LEGAL_VALUES.include?(3) if ext?(:F)
MSTATUS_VS_LEGAL_VALUES:
description: |
The set of values that mstatus.VS will accept from a software write.
schema:
type: array
items:
type: integer
enum: [0,1,2,3]
maxItems: 4
uniqueItems: true
also_defined_in: V
extra_validation: |
assert MSTATUS_VS_LEGAL_VALUES.include?(0) && MSTATUS_VS_LEGAL_VALUES.include?(3) if ext?(:V)

# if HW is writing VS, then Dirty (3) better be a supported value
assert MSTATUS_VS_LEGAL_VALUES.include?(3) if ext?(:V) && (HW_MSTATUS_VS_DIRTY_UPDATE != "never")
MSTATUS_TVM_IMPLEMENTED:
description: |
Whether or not mstatus.TVM is implemented.
Expand Down
32 changes: 31 additions & 1 deletion arch/ext/V.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,34 @@ V:
description: |
Indicates whether or not the `V` extension can be disabled with the `misa.V` bit.
schema:
type: boolean
type: boolean
HW_MSTATUS_VS_DIRTY_UPDATE:
description: |
Indicates whether or not hardware will write to `mstatus.VS`

Values are:
[separator="!"]
!===
h! never ! Hardware never writes `mstatus.VS`
h! precise ! Hardware writes `mstatus.VS` to the Dirty (3) state precisely when V registers are modified
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.
!===
schema:
type: string
enum: ["never", "precise", "imprecise"]
MSTATUS_VS_LEGAL_VALUES:
description: |
The set of values that mstatus.VS will accept from a software write.
schema:
type: array
items:
type: integer
enum: [0,1,2,3]
maxItems: 4
uniqueItems: true
also_defined_in: S
extra_validation: |
assert MSTATUS_VS_LEGAL_VALUES.include?(0) && MSTATUS_VS_LEGAL_VALUES.include?(3) if ext?(:V)

# if HW is writing VS, then Dirty (3) better be a supported value
assert MSTATUS_VS_LEGAL_VALUES.include?(3) if ext?(:V) && (HW_MSTATUS_VS_DIRTY_UPDATE != "never")
41 changes: 41 additions & 0 deletions arch/isa/globals.isa
Original file line number Diff line number Diff line change
Expand Up @@ -2798,3 +2798,44 @@ function write_memory {
}
}

function mstatus_sd_has_known_reset
{
returns Boolean
description {
Returns true if the mstatus.SD bit has a defined reset value, as determined by various parameters.
}
body {
# the reset value is known if both FS and VS are known

Boolean fs_has_single_value =
((!implemented?(ExtensionName::F)) || ($array_size(MSTATUS_FS_LEGAL_VALUES) == 1));

Boolean vs_has_single_value =
((!implemented?(ExtensionName::V)) || ($array_size(MSTATUS_VS_LEGAL_VALUES) == 1));

return fs_has_single_value && vs_has_single_value;
}
}

function mstatus_sd_reset_value
{
returns Bits<1>
description {
Returns the reset value of mstatus.SD when known
}
body {
# the reset value is known if both FS and VS are known
assert(mstatus_sd_has_known_reset());

Bits<2> fs_value, vs_value; # defaults to 0

if ((!implemented?(ExtensionName::F)) || ($array_size(MSTATUS_FS_LEGAL_VALUES) == 1)) {
fs_value = (!implemented?(ExtensionName::F)) ? 0 : MSTATUS_FS_LEGAL_VALUES[0];
}
if ((!implemented?(ExtensionName::V)) || ($array_size(MSTATUS_VS_LEGAL_VALUES) == 1)) {
fs_value = (!implemented?(ExtensionName::V)) ? 0 : MSTATUS_VS_LEGAL_VALUES[0];
}

return ((fs_value == 3) || (vs_value == 3)) ? 1 : 0;
}
}
2 changes: 1 addition & 1 deletion lib/arch_obj_models/csr_field.rb
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ def optional_in_cfg?(arch_def)
exists_in_cfg?(arch_def) &&
(
parent.optional_in_cfg?(arch_def) ||
(data["definedBy"].nil? || arch_def.mandatory_extensions.all? do |ext_req|
(!data["definedBy"].nil? && arch_def.mandatory_extensions.all? do |ext_req|
ext_req.satisfying_versions(arch_def).none? { |ext_ver| defined_by?(ext_ver) }
end)
)
Expand Down
35 changes: 29 additions & 6 deletions lib/idl/ast.rb
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,8 @@ def print_ast(indent = 0, indent_size: 2, io: $stdout)

# @!macro freeze_tree
def freeze_tree(global_symtab)
return if frozen?

@children.each { |child| child.freeze_tree(global_symtab) }
freeze
end
Expand Down Expand Up @@ -1095,6 +1097,8 @@ def initialize(input, interval, user_type)
end

def freeze_tree(global_symtab)
return if frozen?

# call type to get it set before we freeze the object
type(global_symtab)
freeze
Expand Down Expand Up @@ -1257,6 +1261,8 @@ def initialize(input, interval, name, size, fields)

# @!macro freeze_tree
def freeze_tree(global_symtab)
return if frozen?

type(global_symtab)
freeze
end
Expand Down Expand Up @@ -1498,7 +1504,9 @@ def type_check(symtab)
if var.type(symtab).kind == :array
value_result = value_try do
index_value = index.value(symtab)
type_error "Array index out of range" if index_value >= var.type(symtab).width
if var.type(symtab).width != :unknown
type_error "Array index out of range" if index_value >= var.type(symtab).width
end
end # Ok, doesn't need to be known

elsif var.type(symtab).integral?
Expand Down Expand Up @@ -2161,22 +2169,26 @@ def to_ast
class MultiVariableDeclarationAst < AstNode
include Declaration

# @return [AstNode] Declared type
def type_name = @children[0]
def var_names = @children[1..]

# @return [Array<AstNode>] Variable names
def var_name_nodes = @children[1..]

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

@global = false
end

# mark this declaration as being in global scope
def make_global
@global = true
end

# @return [Array<String>] Variables being declared
def var_names
var_names.map(&:text_value)
var_name_nodes.map(&:text_value)
end

# @!macro type_check
Expand All @@ -2186,6 +2198,7 @@ def type_check(symtab)
add_symbol(symtab)
end

# @!macro type
def type(symtab)
if @global
type_name.type(symtab).clone.make_global
Expand All @@ -2196,13 +2209,13 @@ def type(symtab)

# @!macro add_symbol
def add_symbol(symtab)
var_names.each do |vname|
symtab.add(vname.text_values, Var.new(vname.text_value, type(symtab), type(symtab).default))
var_name_nodes.each do |vname|
symtab.add(vname.text_value, Var.new(vname.text_value, type(symtab), type(symtab).default))
end
end

# @!macro to_idl
def to_idl = "#{type_name.to_idl} #{var_names.map(&:to_idl).join(', ')}"
def to_idl = "#{type_name.to_idl} #{var_name_nodes.map(&:to_idl).join(', ')}"
end

class VariableDeclarationSyntaxNode < Treetop::Runtime::SyntaxNode
Expand Down Expand Up @@ -3415,6 +3428,8 @@ def initialize(input, interval, class_name, member_name)

# @!macro freeze_tree
def freeze_tree(global_symtab)
return if frozen?

enum_def_ast = global_symtab.archdef.global_ast.enums.find { |e| e.name == @enum_class_name }

@enum_def_type =
Expand Down Expand Up @@ -4175,6 +4190,8 @@ def type_check(symtab)
end

def freeze_tree(symtab)
return if frozen?

if @type_name == "Bits"
# precalculate size if possible
begin
Expand Down Expand Up @@ -4845,6 +4862,8 @@ def initialize(input, interval, name, targs, return_types, arguments, desc, body

# @!macro freeze_tree
def freeze_tree(global_symtab)
return if frozen?

unless templated?
arguments(global_symtab)
end
Expand Down Expand Up @@ -5675,6 +5694,8 @@ def initialize(input, interval, idx, field_name)
end

def freeze_tree(symtab)
return if frozen?

value_result = value_try do
@value = calc_value(symtab)
end
Expand Down Expand Up @@ -5815,6 +5836,8 @@ def initialize(input, interval, idx)
end

def freeze_tree(symtab)
return if frozen?

@archdef = symtab.archdef # remember archdef, used by gen_adoc pass
@idx.freeze_tree(symtab)
freeze
Expand Down
6 changes: 6 additions & 0 deletions lib/idl/passes/gen_option_adoc.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@ def gen_option_adoc
end
end

class FunctionCallExpressionAst
def gen_option_adoc
gen_adoc(0)
end
end

class IfAst
def gen_option_adoc
adoc =
Expand Down
Loading
Loading