Class: Idl::AryRangeAssignmentAst
- Inherits:
-
AstNode
- Object
- AstNode
- Idl::AryRangeAssignmentAst
show all
- Includes:
- Executable
- Defined in:
- lib/idlc/ast.rb,
lib/idlc/passes/prune.rb,
lib/idlc/passes/prune.rb,
lib/idlc/passes/gen_adoc.rb,
lib/idlc/passes/find_src_registers.rb
Overview
represents an array range assignment
for example:
vec[8:0] = 8'd0
Constant Summary
Constants inherited
from AstNode
Idl::AstNode::Bits1Type, Idl::AstNode::Bits32Type, Idl::AstNode::Bits64Type, Idl::AstNode::BoolType, Idl::AstNode::ConstBoolType, Idl::AstNode::PossiblyUnknownBits1Type, Idl::AstNode::PossiblyUnknownBits32Type, Idl::AstNode::PossiblyUnknownBits64Type, Idl::AstNode::ReachableFunctionCacheType, Idl::AstNode::StringType, Idl::AstNode::VoidType
Instance Attribute Summary
Attributes inherited from AstNode
#children, #input, #interval, #parent
Class Method Summary
collapse
Instance Method Summary
collapse
Methods included from Executable
#executable?
Methods inherited from AstNode
#always_terminates?, #declaration?, #executable?, extract_base_var_name, #find_ancestor, #find_referenced_csrs, #find_src_registers, #freeze_tree, #gen_option_adoc, #input_file, input_from_source_yaml, #inspect, #internal_error, interval_from_source_yaml, #lineno, #lines_around, #pass_find_return_values, #path, #print_ast, #reachable_exceptions, #reachable_functions, #set_input_file, #set_input_file_unless_already_set, #source_line_file_offsets, #source_starting_offset, #source_yaml, #starting_line, #text_value, #truncation_warn, #type_error, #unindent, value_else, #value_else, value_error, #value_error, value_try, #value_try, write_back_nested
Constructor Details
#initialize(input, interval, variable, msb, lsb, write_value) ⇒ AryRangeAssignmentAst
Returns a new instance of AryRangeAssignmentAst.
3105
3106
3107
|
# File 'lib/idlc/ast.rb', line 3105
def initialize(input, interval, variable, msb, lsb, write_value)
super(input, interval, [variable, msb, lsb, write_value])
end
|
Class Method Details
.from_h(yaml, source_mapper) ⇒ Object
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
|
# File 'lib/idlc/ast.rb', line 3195
def self.from_h(yaml, source_mapper)
raise "Bad YAML" unless yaml.key?("kind") && yaml.fetch("kind") == "array_range_assignment"
input = input_from_source_yaml(yaml.fetch("source"), source_mapper)
interval = interval_from_source_yaml(yaml.fetch("source"))
AryRangeAssignmentAst.new(
input, interval,
T.cast(AstNode.from_h(yaml.fetch("array"), source_mapper), RvalueAst),
T.cast(AstNode.from_h(yaml.fetch("range").fetch("msb"), source_mapper), RvalueAst),
T.cast(AstNode.from_h(yaml.fetch("range").fetch("lsb"), source_mapper), RvalueAst),
T.cast(AstNode.from_h(yaml.fetch("value"), source_mapper), RvalueAst)
)
end
|
Instance Method Details
#const_eval?(symtab) ⇒ Boolean
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
|
# File 'lib/idlc/ast.rb', line 3084
def const_eval?(symtab)
return false if !variable.const_eval?(symtab)
if lsb.const_eval?(symtab) && msb.const_eval?(symtab) && write_value.const_eval?(symtab)
true
else
base_name = AstNode.(variable)
type_error "Cannot determine base variable for #{variable.text_value}" if base_name.nil?
lhs_var = symtab.get(base_name)
type_error "array #{base_name} has not be declared" if lhs_var.nil?
lhs_var.const_incompatible!
false
end
end
|
#execute(symtab) ⇒ void
This method returns an undefined value.
“execute” the statement by updating the variables in the symbol table
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
|
# File 'lib/idlc/ast.rb', line 3148
def execute(symtab)
return if variable.type(symtab).global?
value_result = value_try do
msb_val = msb.value(symtab)
lsb_val = lsb.value(symtab)
type_error "MSB (#{msb_val}) is <= LSB (#{lsb_val})" if msb_val <= lsb_val
rval_val = write_value.value(symtab)
mask = ((1 << (msb_val - lsb_val + 1)) - 1) << lsb_val
var_val = variable.value(symtab)
var_val &= ~mask
new_val = var_val | ((rval_val << lsb_val) & mask)
AstNode.write_back_nested(variable, new_val, symtab)
:ok
end
value_else(value_result) do
base_name = T.must(AstNode.(variable))
v = symtab.get(base_name)
internal_error "did not find array base" if v.nil?
v.value = nil
value_error "Either the range or right-hand side of an array range assignment is unknown"
end
end
|
#find_dst_registers(symtab) ⇒ Object
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
|
# File 'lib/idlc/passes/find_src_registers.rb', line 143
def find_dst_registers(symtab)
return [] unless variable.is_a?(Idl::AryElementAccessAst)
var_type = variable.var.type(symtab) rescue nil
return [] unless var_type&.kind == :array &&
var_type.sub_type.is_a?(RegFileElementType) &&
var_type.qualifiers.include?(:global)
rf_name = var_type.sub_type.name
value_result = value_try do
return [[rf_name, variable.index.value(symtab)]]
end
value_else(value_result) do
if variable.index.type(symtab).const?
return [[rf_name, variable.index.gen_cpp(symtab, 0)]]
else
raise ComplexRegDetermination
end
end
end
|
#gen_adoc(indent = 0, indent_spaces: 2) ⇒ Object
20
21
22
|
# File 'lib/idlc/passes/gen_adoc.rb', line 20
def gen_adoc(indent = 0, indent_spaces: 2)
"#{' ' * indent}#{variable.gen_adoc(indent, indent_spaces:)}[#{msb.gen_adoc(0, indent_spaces:)}:#{lsb.gen_adoc(0, indent_spaces:)}] = #{write_value.gen_adoc(0, indent_spaces:)}"
end
|
#lsb ⇒ Object
3102
|
# File 'lib/idlc/ast.rb', line 3102
def lsb = @children[2]
|
#msb ⇒ Object
3101
|
# File 'lib/idlc/ast.rb', line 3101
def msb = @children[1]
|
#nullify_assignments(symtab) ⇒ Object
170
171
172
173
174
175
176
|
# File 'lib/idlc/passes/prune.rb', line 170
def nullify_assignments(symtab)
return if variable.type(symtab).global?
root = variable
root = root.var while root.is_a?(AryElementAccessAst) || root.is_a?(AryRangeAccessAst)
var = symtab.get(root.name)
var.value = nil unless var.nil?
end
|
#prune(symtab, forced_type: nil) ⇒ Object
914
915
916
917
918
919
920
921
922
923
924
925
926
927
|
# File 'lib/idlc/passes/prune.rb', line 914
def prune(symtab, forced_type: nil)
new_ast = AryRangeAssignmentAst.new(
input, interval,
variable.dup,
msb.prune(symtab),
lsb.prune(symtab),
write_value.prune(symtab)
)
value_try do
new_ast.execute(symtab)
end
new_ast
end
|
#rhs ⇒ Object
3143
3144
3145
|
# File 'lib/idlc/ast.rb', line 3143
def rhs
write_value
end
|
#to_h ⇒ Object
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
|
# File 'lib/idlc/ast.rb', line 3183
def to_h = {
"kind" => "array_range_assignment",
"array" => variable.to_h,
"range" => {
"lsb" => lsb.to_h,
"msb" => msb.to_h
},
"value" => write_value.to_h,
"source" => source_yaml
}
|
#to_idl ⇒ Object
3180
|
# File 'lib/idlc/ast.rb', line 3180
def to_idl = "#{variable.to_idl}[#{msb.to_idl}:#{lsb.to_idl}] = #{write_value.to_idl}"
|
#type_check(symtab, strict:) ⇒ void
This method returns an undefined value.
type check this node and all children
Calls to #type and/or #value may depend on type_check being called first with the same symtab. If not, those functions may raise an AstNode::InternalError
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
|
# File 'lib/idlc/ast.rb', line 3110
def type_check(symtab, strict:)
variable.type_check(symtab, strict:)
type_error "#{variable.text_value} must be integral" unless variable.type(symtab).kind == :bits
type_error "Assigning to a constant" if variable.type(symtab).const?
msb.type_check(symtab, strict:)
lsb.type_check(symtab, strict:)
type_error "MSB must be integral" unless msb.type(symtab).integral?
type_error "LSB must be integral" unless lsb.type(symtab).integral?
value_result = value_try do
msb_value = msb.value(symtab)
lsb_value = lsb.value(symtab)
type_error "MSB must be > LSB" unless msb_value > lsb_value
if variable.type(symtab).width == :unknown
unless variable.type(symtab).max_width.nil?
type_error "MSB is out of range" if msb_value >= variable.type(symtab).max_width
end
else
type_error "MSB is out of range" if msb_value >= variable.type(symtab).width
end
end
write_value.type_check(symtab, strict:)
unless write_value.type(symtab).integral?
type_error "Incompatible type in range assignment"
end
end
|
#variable ⇒ Object
3100
|
# File 'lib/idlc/ast.rb', line 3100
def variable = @children[0]
|
#write_value ⇒ Object
3103
|
# File 'lib/idlc/ast.rb', line 3103
def write_value = @children[3]
|