Skip to content

Commit b41b394

Browse files
author
Derek Hower
committed
Adjust ArchGen to account for json references
1 parent d729038 commit b41b394

File tree

3 files changed

+28
-112
lines changed

3 files changed

+28
-112
lines changed

backends/arch_gen/lib/arch_gen.rb

Lines changed: 15 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ def gen_params_schema
5252
@implemented_extensions.each do |ext|
5353
ext_name = ext["name"]
5454
gen_ext_path = @gen_dir / "arch" / "ext" / "#{ext_name}.yaml"
55-
ext_yaml = YamlLoader.load gen_ext_path.to_s
55+
ext_yaml = YAML.load_file gen_ext_path.to_s
5656
unless ext_yaml[ext_name]["params"].nil?
5757
ext_yaml[ext_name]["params"].each do |param_name, param_data|
5858
schema["properties"]["params"]["required"] << param_name
@@ -146,7 +146,7 @@ def params_extra_validation
146146
@implemented_extensions.each do |ext|
147147
ext_name = ext["name"]
148148
gen_ext_path = @gen_dir / "arch" / "ext" / "#{ext_name}.yaml"
149-
ext_yaml = YamlLoader.load gen_ext_path.read
149+
ext_yaml = YAML.load_file gen_ext_path.read
150150
unless ext_yaml[ext_name]["params"].nil?
151151
ext_yaml[ext_name]["params"].each do |param_name, param_data|
152152
next unless param_data.key?("extra_validation")
@@ -545,99 +545,6 @@ def arch_overlay_path_for(type, name)
545545
def schema_path_for(type) = Validator::SCHEMA_PATHS[type]
546546
private :schema_path_for
547547

548-
# Render a architecture definition file and save it to gen_dir / .rendered_arch
549-
#
550-
# Will not re-render if rendered file already exists and sources have not changed
551-
#
552-
# @param type [Symbol] Type of the object (@see Validator::SCHEMA_PATHS)
553-
# @param name [#to_s] Name of the object
554-
# @param extra_env [Hash,NilObject] Optional hash with extra enviornment variables for the render
555-
# @return [Pathname,nil] Path to generated file, or nil if there is no (valid) definition for type,name
556-
def gen_rendered_arch_def(type, name, extra_env = {})
557-
gen_path = @gen_dir / ".rendered_arch" / type.to_s / "#{name}.yaml"
558-
559-
source_path = arch_path_for(type, name)
560-
return nil if source_path.nil?
561-
562-
schema_path = schema_path_for(type)
563-
564-
if gen_path.exist?
565-
# this already exists...see if we need to regenerate it
566-
dep_mtime = [File.mtime(__FILE__), source_path.mtime, schema_path.mtime].max
567-
return gen_path if gen_path.mtime >= dep_mtime # no update needed
568-
end
569-
570-
trace "Rendering architecture file for #{type}:#{name}"
571-
572-
# render the source template
573-
current_env = env.clone
574-
extra_env&.each { |k, v| current_env.define_singleton_method(k) { v } }
575-
rendered_def = Tilt["erb"].new(source_path, trim: "-").render(current_env)
576-
577-
# see if the rendering was empty, meaning that the def isn't valid in this config
578-
return nil if rendered_def.nil?
579-
580-
# write the object
581-
FileUtils.mkdir_p gen_path.dirname
582-
File.write(gen_path, rendered_def)
583-
584-
# verify
585-
begin
586-
@validator.validate_str(rendered_def, type:)
587-
rescue Validator::SchemaValidationError => e
588-
warn "#{type} definition in #{source_path} did not validate"
589-
raise e
590-
end
591-
592-
def_obj = YamlLoader.load(rendered_def)
593-
594-
raise "#{type} name ('#{name}') must match key in defintion ('#{def_obj.keys[0]}')" if name.to_s != def_obj.keys[0]
595-
596-
# return path to generated file
597-
gen_path
598-
end
599-
private :gen_rendered_arch_def
600-
601-
# Render a architecture overlay definition file and save it to gen_dir / .rendered_overlay_arch
602-
#
603-
# Will not re-render if rendered file already exists and sources have not changed
604-
#
605-
# @param type [Symbol] Type of the object (@see Validator::SCHEMA_PATHS)
606-
# @param name [#to_s] Name of the object
607-
# @param extra_env [Hash,NilObject] Optional hash with extra enviornment variables for the render
608-
# @return [Pathname] Path to generated file
609-
def gen_rendered_arch_overlay_def(type, name, extra_env = {})
610-
gen_path = @gen_dir / ".rendered_overlay_arch" / type.to_s / "#{name}.yaml"
611-
612-
source_path = arch_overlay_path_for(type, name)
613-
return nil if source_path.nil?
614-
615-
if gen_path.exist?
616-
# this already exists...see if we need to regenerate it
617-
dep_mtime = [File.mtime(__FILE__), source_path.mtime].max
618-
return gen_path if gen_path.mtime >= dep_mtime # no update needed
619-
end
620-
621-
trace "Rendering overlay file for #{type}:#{name}"
622-
623-
# render the source template
624-
current_env = env.clone
625-
extra_env&.each { |k, v| current_env.define_singleton_method(k) { v } }
626-
rendered_def = Tilt["erb"].new(source_path, trim: "-").render(current_env)
627-
628-
def_obj = YamlLoader.load(rendered_def)
629-
630-
raise "#{type} name (#{name}) must match key in defintion (#{def_obj.keys[0]})" if name.to_s != def_obj.keys[0]
631-
632-
# write the object
633-
FileUtils.mkdir_p gen_path.dirname
634-
File.write(gen_path, YAML.dump(def_obj))
635-
636-
# return path to generated file
637-
gen_path
638-
end
639-
private :gen_rendered_arch_overlay_def
640-
641548
# generate a merged definition from rendered arch and overlay, and write it to gen / .merged_arch
642549
#
643550
# Skips if gen file already exists and sources are older
@@ -665,10 +572,12 @@ def gen_merged_def(type, arch_path, overlay_path)
665572
FileUtils.mkdir_p merged_path.dirname
666573
if overlay_path.nil?
667574
# no overlay, just copy arch
668-
FileUtils.cp arch_path, merged_path
575+
merged_path.write YAML.dump(YamlLoader.load(arch_path))
576+
# FileUtils.cp arch_path, merged_path
669577
elsif arch_path.nil?
670578
# no arch, overlay is arch
671-
FileUtils.cp overlay_path, merged_path
579+
merged_path.write YAML.dump(YamlLoader.load(overlay_path))
580+
# FileUtils.cp overlay_path, merged_path
672581
else
673582
# arch and overlay, do the merge
674583
arch_obj = YamlLoader.load(arch_path)
@@ -695,8 +604,8 @@ def gen_merged_def(type, arch_path, overlay_path)
695604
# @param csr_name [#to_s] CSR name
696605
# @param extra_env [Hash] Extra enviornment variables to be used when parsing the CSR definition template
697606
def maybe_add_csr(csr_name, extra_env = {})
698-
arch_path = arch_path_for(:csr, csr_name) # gen_rendered_arch_def(:csr, csr_name, extra_env)
699-
arch_overlay_path = arch_overlay_path_for(:csr, csr_name) # gen_rendered_arch_overlay_def(:csr, csr_name, extra_env)
607+
arch_path = arch_path_for(:csr, csr_name)
608+
arch_overlay_path = arch_overlay_path_for(:csr, csr_name)
700609

701610
# return immediately if this CSR isn't defined in this config
702611
raise "No arch or overlay for sr #{csr_name}" if arch_path.nil? && arch_overlay_path.nil?
@@ -721,7 +630,7 @@ def maybe_add_csr(csr_name, extra_env = {})
721630
end
722631

723632
# get the csr data (not including the name key), which is redundant at this point
724-
csr_data = YamlLoader.load(merged_path)[csr_name]
633+
csr_data = YAML.load_file(merged_path)[csr_name]
725634
csr_data["name"] = csr_name
726635
csr_data["fields"].each { |n, f| f["name"] = n }
727636
csr_data["__source"] = og_path.to_s
@@ -796,15 +705,15 @@ def all_known_exts
796705
end
797706

798707
def maybe_add_ext(ext_name)
799-
arch_path = arch_path_for(:ext, ext_name) # gen_rendered_arch_def(:ext, ext_name)
800-
arch_overlay_path = arch_overlay_path_for(:ext, ext_name) # gen_rendered_arch_overlay_def(:ext, ext_name)
708+
arch_path = arch_path_for(:ext, ext_name)
709+
arch_overlay_path = arch_overlay_path_for(:ext, ext_name)
801710

802711
# return immediately if this ext isn't defined
803712
return if arch_path.nil? && arch_overlay_path.nil?
804713

805714
merged_path = gen_merged_def(:ext, arch_path, arch_overlay_path)
806715

807-
yaml_contents = YamlLoader.load(merged_path)
716+
yaml_contents = YAML.load_file(merged_path)
808717
raise "In #{merged_path}, key does not match file name" unless yaml_contents.key?(ext_name)
809718

810719
ext_obj = yaml_contents[ext_name]
@@ -940,8 +849,8 @@ def possible_xlens
940849
# @param inst_name [#to_s] instruction name
941850
# @param extra_env [Hash] Extra options to add into the rendering enviornment
942851
def maybe_add_inst(inst_name, extra_env = {})
943-
arch_path = arch_path_for(:inst, inst_name) # gen_rendered_arch_def(:inst, inst_name, extra_env)
944-
arch_overlay_path = arch_overlay_path_for(:inst, inst_name) # gen_rendered_arch_overlay_def(:inst, inst_name, extra_env)
852+
arch_path = arch_path_for(:inst, inst_name)
853+
arch_overlay_path = arch_overlay_path_for(:inst, inst_name)
945854

946855
# return immediately if inst isn't defined in this config
947856
raise "No arch or overlay for instruction #{inst_name}" if arch_path.nil? && arch_overlay_path.nil?
@@ -966,7 +875,7 @@ def maybe_add_inst(inst_name, extra_env = {})
966875
end
967876

968877
# get the inst data (not including the name key), which is redundant at this point
969-
inst_data = YamlLoader.load(merged_path)
878+
inst_data = YAML.load_file(merged_path)
970879
raise "The first and only key of #{arch_path} must be '#{inst_name}" unless inst_data.key?(inst_name)
971880
inst_data = inst_data[inst_name]
972881

lib/validate.rb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# frozen_string_literal: true
22

3+
require_relative "yaml_loader"
4+
35
require "date"
46
require "json"
57
require "json_schemer"
@@ -256,7 +258,7 @@ def validate_instruction_encoding(inst_name, encoding)
256258
# @param path [Pathname] Path to an instruction YAML document
257259
# @raise [ValidateError] if there is a problem with the instruction defintion
258260
def validate_instruction(path)
259-
obj = YAML.load_file(path)
261+
obj = YamlLoader.load(path)
260262
raise "Invalid instruction definition: #{obj}" unless obj.is_a?(Hash)
261263

262264
inst_name = path.basename('.yaml').to_s

lib/yaml_loader.rb

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# frozen_string_literal: true
22

3+
require "pathname"
34
require "yaml"
45

56
# loads a YAML file and expands any $ref/$mref references
@@ -22,8 +23,11 @@ def self.expand(filename, obj, yaml_opts = {})
2223

2324
if key == "$mref"
2425
relative_path = value.split("#")[0]
25-
target_filename = File.realpath(File.join(File.dirname(filename), relative_path))
26-
raise "#{target_filename} does not exist" unless File.exist?(target_filename)
26+
target_filename = File.realpath(File.join(filename.dirname, relative_path))
27+
28+
unless File.exist?(target_filename)
29+
raise "While locating $mref in #{filename}, #{target_filename} does not exist"
30+
end
2731

2832
target_obj = YamlLoader.load(target_filename, yaml_opts)
2933
target_obj = target_obj.dig(*value.split("#/")[1].split("/"))
@@ -44,14 +48,15 @@ def self.expand(filename, obj, yaml_opts = {})
4448
# @param yaml_opts [Hash] options to pass to YAML.load_file
4549
# @return [Object] the loaded YAML file
4650
def self.load(filename, yaml_opts = {})
47-
raise ArgumentError, "Cannot find file #{filename}" unless File.exist?(filename)
51+
filename = Pathname.new(filename)
52+
raise ArgumentError, "Cannot find file #{filename}" unless filename.exist?
4853

49-
filename = File.realpath(filename)
54+
filename = filename.realpath
5055
return @cache[filename] if @cache.key?(filename)
5156

5257
obj = YAML.load_file(filename, **yaml_opts)
5358
obj = expand(filename, obj, yaml_opts) if obj.is_a?(Hash)
5459

55-
@cache[filename] = obj
60+
# @cache[filename] = obj
5661
end
5762
end

0 commit comments

Comments
 (0)