Compare commits

..

No commits in common. "014112b93ac0ce0b17177253b7f5e958bc01ae2f" and "5ada904040e6c39f628a44e249fc83db27a87320" have entirely different histories.

30 changed files with 222 additions and 844 deletions

1
.gitignore vendored
View file

@ -6,4 +6,3 @@
/pkg/ /pkg/
/spec/reports/ /spec/reports/
/tmp/ /tmp/
/build/

View file

@ -10,54 +10,51 @@ GEM
backport (1.2.0) backport (1.2.0)
benchmark (0.2.1) benchmark (0.2.1)
coderay (1.1.3) coderay (1.1.3)
debug (1.8.0) debug (1.7.2)
irb (>= 1.5.0) irb (>= 1.5.0)
reline (>= 0.3.1) reline (>= 0.3.1)
diff-lcs (1.5.0) diff-lcs (1.5.0)
e2mmap (0.1.0) e2mmap (0.1.0)
io-console (0.6.0) io-console (0.6.0)
irb (1.7.4) irb (1.6.4)
reline (>= 0.3.6) reline (>= 0.3.0)
jaro_winkler (1.5.6) jaro_winkler (1.5.4)
json (2.6.3) json (2.6.3)
kramdown (2.4.0) kramdown (2.4.0)
rexml rexml
kramdown-parser-gfm (1.1.0) kramdown-parser-gfm (1.1.0)
kramdown (~> 2.0) kramdown (~> 2.0)
language_server-protocol (3.17.0.3)
method_source (1.0.0) method_source (1.0.0)
minitest (5.18.1) minitest (5.18.0)
nokogiri (1.15.3-x86_64-linux) nokogiri (1.14.3-x86_64-linux)
racc (~> 1.4) racc (~> 1.4)
parallel (1.23.0) parallel (1.22.1)
parser (3.2.2.3) parser (3.2.2.0)
ast (~> 2.4.1) ast (~> 2.4.1)
racc
pry (0.14.2) pry (0.14.2)
coderay (~> 1.1) coderay (~> 1.1)
method_source (~> 1.0) method_source (~> 1.0)
racc (1.7.1) racc (1.6.2)
rainbow (3.1.1) rainbow (3.1.1)
rake (13.0.6) rake (13.0.6)
rbs (2.8.4) rbs (2.8.4)
regexp_parser (2.8.1) regexp_parser (2.7.0)
reline (0.3.6) reline (0.3.3)
io-console (~> 0.5) io-console (~> 0.5)
reverse_markdown (2.1.1) reverse_markdown (2.1.1)
nokogiri nokogiri
rexml (3.2.5) rexml (3.2.5)
rubocop (1.54.2) rubocop (1.50.1)
json (~> 2.3) json (~> 2.3)
language_server-protocol (>= 3.17.0)
parallel (~> 1.10) parallel (~> 1.10)
parser (>= 3.2.2.3) parser (>= 3.2.0.0)
rainbow (>= 2.2.2, < 4.0) rainbow (>= 2.2.2, < 4.0)
regexp_parser (>= 1.8, < 3.0) regexp_parser (>= 1.8, < 3.0)
rexml (>= 3.2.5, < 4.0) rexml (>= 3.2.5, < 4.0)
rubocop-ast (>= 1.28.0, < 2.0) rubocop-ast (>= 1.28.0, < 2.0)
ruby-progressbar (~> 1.7) ruby-progressbar (~> 1.7)
unicode-display_width (>= 2.4.0, < 3.0) unicode-display_width (>= 2.4.0, < 3.0)
rubocop-ast (1.29.0) rubocop-ast (1.28.0)
parser (>= 3.2.1.0) parser (>= 3.2.1.0)
ruby-progressbar (1.13.0) ruby-progressbar (1.13.0)
solargraph (0.49.0) solargraph (0.49.0)
@ -76,10 +73,10 @@ GEM
thor (~> 1.0) thor (~> 1.0)
tilt (~> 2.0) tilt (~> 2.0)
yard (~> 0.9, >= 0.9.24) yard (~> 0.9, >= 0.9.24)
thor (1.2.2) thor (1.2.1)
tilt (2.2.0) tilt (2.1.0)
unicode-display_width (2.4.2) unicode-display_width (2.4.2)
yard (0.9.34) yard (0.9.33)
PLATFORMS PLATFORMS
x86_64-linux x86_64-linux

View file

@ -12,20 +12,145 @@ $core = Comfpile::Core.new()
$core.add_artefact_engine Comfpile::FilesourceEngine, root_path: File.join(File.dirname(__FILE__), '../test/faux_build_dir') $core.add_artefact_engine Comfpile::FilesourceEngine, root_path: File.join(File.dirname(__FILE__), '../test/faux_build_dir')
$core.add_artefact_engine Comfpile::ConfigLoaderEngine $core.add_artefact_engine Comfpile::ConfigLoaderEngine
require_relative 'ghdl_engine.rb' $core.add_artefact_engine Comfpile::ParserEngine,
require_relative 'cpp_engine.rb' file_regex: /^(.+)\.(h|c|cpp)$/,
search_regexes: [
{
regex: /^#include\s*[<"](?<value>.+)[>"]/,
key: 'include'
},
{
regex: /\/\/\s*comf\.(?<key>\w+)[=:]\s*(?<value>.+)/
}
]
$core.add_artefact_engine Comfpile::ParserEngine,
file_regex: /^(.+)\.vhd$/,
search_regexes: [
{
regex: /--+\s*comf\.(?<key>[^:]+)[=:]\s*(?<value>.+)/
}
]
$core.add_artefact_engine do |engine|
engine.add_recipe(:ghdl_analysed, /^(.+)\.vhd/) do |match, a|
a.parent_artefact :dependency_analysis_include, a.target
a.add_step do
@parent_artefact.dependencies.each do |dependency|
next if dependency.target == a.target
log "Adding dependency for ghdl analysis of #{dependency.target}..."
require_artefact :ghdl_analysed, dependency.target
end
end
a.add_step do
work_library = find_parsed_parameter('vhdl.work')
if work_library.nil?
work_library = ''
else
work_library = '--work=' + work_library
end
cmd = "ghdl -a -fsynopsys --std=08 #{work_library} #{self.file}"
log "Executing: #{cmd}"
`#{cmd}`
end
end
engine.add_recipe(:ghdl_elaborated, /^(.+)\.vhd/) do |match, a|
a.parent_artefact :dependency_analysis, a.target
a.add_step do
dependencies.each do |dep|
require_artefact :ghdl_analysed, dep.target
end
end
a.add_step do
work_library = find_parsed_parameter('vhdl.work')
if work_library.nil?
work_library = ''
else
work_library = '--work=' + work_library
end
elaborate_arch = find_parsed_parameter('vhdl.elaborate') || File.basename(@target).chomp(File.extname(@target))
cmd = "ghdl -e -fsynopsys --std=08 #{work_library} #{elaborate_arch}"
log "Executing: #{cmd}"
`#{cmd}`
end
end
engine.add_recipe :ghdl_run, /^(.+)\.vhd/ do |match, a|
a.parent_artefact :ghdl_elaborated, a.target
a.add_step do
work_library = find_parsed_parameter('vhdl.work')
if work_library.nil?
work_library = ''
else
work_library = '--work=' + work_library
end
elaborate_arch = find_parsed_parameter('vhdl.elaborate') || File.basename(@target).chomp(File.extname(@target))
@parameters[:ghdl_arch] = elaborate_arch
cmd = "ghdl -r -fsynopsys --std=08 #{work_library} #{elaborate_arch} --wave=#{elaborate_arch}.ghw"
log "Executing: #{cmd}"
`#{cmd}`
end
end
engine.add_recipe(:gtkwave_output, /^(.+)\.vhd/) do |match, a|
a.parent_artefact :ghdl_run, a.target
a.add_step do
`gtkwave #{@parent_artefact[:ghdl_arch]}.ghw`
end
end
end
$core.add_artefact_engine do |engine|
engine.add_recipe(:dependency_list, /^(.+)\.(h|c|cpp)$/) do |match, a|
a.require_artefact :dependency_analysis, a.target
a.require_artefact :dependency_analysis_include, a.target
a.add_step do
deps_artefact = find_artefact(:dependency_analysis, @target)
@parameters[:dependency_list] = deps_artefact.dependencies
end
end
engine.add_recipe(:x86_debug, /^run (.+)/) do |match, a|
a.require_artefact :parsed, "#{match[1]}.cpp"
end
engine.add_recipe(:x86_debug, /(.+)\.o$/) do |match, a|
a.require_artefact :sourcefile, "#{match[1]}.cpp"
a.add_step do
end
true
end
end
t_start = Time.now() t_start = Time.now()
dep_art = $core.craft_and_complete(:execute, "cpp/main.cpp") dep_art = $core.craft_and_complete(:gtkwave_output, "spi_master_tb.vhd")
dep_art = $core.craft_and_complete(:execute, "cpp/main2.cpp")
t_end = Time.now() t_end = Time.now()
# t_start = Time.now() puts "Full dependency list is: #{dep_art.dependencies.map(&:target)} (took #{t_end - t_start})"
# dep_art = $core.craft_and_complete(:gtkwave_output, "vhdl/spi_master_tb.vhd") puts "Includes of all source files:"
# t_end = Time.now()
# puts "Full dependency list is: #{dep_art.dependencies.map(&:target)} (took #{t_end - t_start})"
# puts "Includes of all source files:"
# (If you use this, don't forget to add pry to your Gemfile!) # (If you use this, don't forget to add pry to your Gemfile!)
require "pry" require "pry"

View file

@ -1,48 +0,0 @@
$core.add_artefact_engine Comfpile::ParserEngine,
file_regex: /^(.+)\.(h|c|cpp)$/,
search_regexes: [
{
regex: /^#include\s*[<"](?<value>.+)[>"]/,
key: 'include'
},
{
regex: /\/\/\s*comf\.(?<key>\w+)[=:]\s*(?<value>.+)/
}
]
$core.add_artefact_engine do |engine|
engine.add_recipe(:dependency_list, /^(.+)\.(h|c|cpp)$/) do |match, a|
a.require_artefact :dependency_analysis, a.target
a.require_artefact :dependency_analysis_include, a.target
a.add_step do
deps_artefact = find_artefact(:dependency_analysis, @target)
@parameters[:dependency_list] = deps_artefact.dependencies
end
end
engine.add_recipe(:x86_debug, /^run (.+)/) do |match, a|
a.require_artefact :parsed, "#{match[1]}.cpp"
end
engine.add_recipe(:x86_debug, /(.+)\.o$/) do |match, a|
a.require_artefact :sourcefile, "#{match[1]}.cpp"
a.add_step do
end
end
engine.add_recipe(:execute, /(.*)/) do |match, a|
a.parent_artefact :executable, match[0]
a.add_step do
@parent_artefact
end
end
end

View file

@ -1,72 +0,0 @@
$core.add_artefact_engine Comfpile::ParserEngine,
file_regex: /^(.+)\.(h|c|cpp)$/,
search_regexes: [
{
regex: /^#include\s*[<"](?<value>.+)[>"]/,
key: 'include'
},
{
regex: /\/\/\s*comf\.(?<key>\w+)[=:]?\s*(?<value>.+)/
}
]
$core.add_artefact_engine do |engine|
engine.add_recipe(:object, /^(.*)\.(h|c|cpp)$/) do |match, a|
a.parent_artefact :sourcefile, match[0]
a.add_step do
`g++ -I #{@build_dir} -c #{@target} -o #{@target}.o`
end
end
engine.add_recipe(:main_object, /^(.*)\.(h|c|cpp)$/) do |match, a|
a.parent_artefact :sourcefile, match[0]
a.add_step do
`g++ -DCOMF_MAIN -I #{@build_dir} -c #{@target} -o #{@target}.main.o`
end
end
engine.add_recipe(:executable) do |match, a|
a.parent_artefact :dependency_analysis, match
a.add_step do
@object_files = []
@parent_artefact.dependencies.each do |dep|
next unless ['.c', '.cpp'].include? File.extname(dep.target)
next if dep.target == @target
@object_files << require_artefact(:object, dep.target)
end
@main_object_file = require_artefact(:main_object, @target)
end
a.add_step do
link_objects = []
@object_files.each do |obj|
link_objects << obj.target + '.o'
end
link_objects << @main_object_file.target + '.main.o'
cmd = "g++ #{link_objects.join(' ')} -o #{@target.sub(/\.[^.\/]*\Z/, '')}"
log cmd
`#{cmd}`
end
end
engine.add_recipe(:execute) do |match, a|
a.parent_artefact :executable, match
a.add_step do
print "\n\nPROGRAM OUTPUT FOR #{match}:\n"
print `./#{@target.sub(/\.[^.\/]*\Z/, '')}`
print "\n\n"
end
end
end

View file

@ -1,94 +0,0 @@
$core.add_artefact_engine Comfpile::ParserEngine,
file_regex: /^(.+)\.vhd$/,
search_regexes: [
{
regex: /--+\s*comf\.(?<key>[^:]+)[=:]\s*(?<value>.+)/
}
]
$core.add_artefact_engine do |engine|
engine.add_recipe(:ghdl_analysed, /^(.+)\.vhd/) do |match, a|
a.parent_artefact :dependency_analysis_include, a.target
a.add_step do
@parent_artefact.dependencies.each do |dependency|
next if dependency.target == a.target
log "Adding dependency for ghdl analysis of #{dependency.target}..."
require_artefact :ghdl_analysed, dependency.target
end
end
a.add_step do
work_library = find_parsed_parameter('vhdl.work')
if work_library.nil?
work_library = ''
else
work_library = '--work=' + work_library
end
cmd = "ghdl -a -fsynopsys --std=08 #{work_library} #{self.file}"
log "Executing: #{cmd}"
`#{cmd}`
end
end
engine.add_recipe(:ghdl_elaborated, /^(.+)\.vhd/) do |match, a|
a.parent_artefact :dependency_analysis, a.target
a.add_step do
dependencies.each do |dep|
require_artefact :ghdl_analysed, dep.target
end
end
a.add_step do
work_library = find_parsed_parameter('vhdl.work')
if work_library.nil?
work_library = ''
else
work_library = '--work=' + work_library
end
elaborate_arch = find_parsed_parameter('vhdl.elaborate') || File.basename(@target).chomp(File.extname(@target))
cmd = "ghdl -e -fsynopsys --std=08 #{work_library} #{elaborate_arch}"
log "Executing: #{cmd}"
`#{cmd}`
end
end
engine.add_recipe :ghdl_run, /^(.+)\.vhd/ do |match, a|
a.parent_artefact :ghdl_elaborated, a.target
a.add_step do
work_library = find_parsed_parameter('vhdl.work')
if work_library.nil?
work_library = ''
else
work_library = '--work=' + work_library
end
elaborate_arch = find_parsed_parameter('vhdl.elaborate') || File.basename(@target).chomp(File.extname(@target))
@parameters[:ghdl_arch] = elaborate_arch
cmd = "ghdl -r -fsynopsys --std=08 #{work_library} #{elaborate_arch} --wave=#{elaborate_arch}.ghw"
log "Executing: #{cmd}"
`#{cmd}`
end
end
engine.add_recipe(:gtkwave_output, /^(.+)\.vhd/) do |match, a|
a.parent_artefact :ghdl_run, a.target
a.add_step do
`gtkwave #{@parent_artefact[:ghdl_arch]}.ghw`
end
end
end

View file

@ -4,9 +4,5 @@
"path": "." "path": "."
} }
], ],
"settings": { "settings": {}
"conventionalCommits.scopes": [
"context"
]
}
} }

View file

@ -6,6 +6,4 @@ require_relative 'comfpile/core.rb'
require_relative 'comfpile/engines/filesource_engine.rb' require_relative 'comfpile/engines/filesource_engine.rb'
require_relative 'comfpile/engines/parser_engine.rb' require_relative 'comfpile/engines/parser_engine.rb'
require_relative 'comfpile/engines/config_engine.rb' require_relative 'comfpile/engines/config_engine.rb'
require_relative 'comfpile/context.rb'

View file

@ -8,9 +8,6 @@ module Comfpile
class Artefact class Artefact
attr_reader :core, :engine attr_reader :core, :engine
# @return [Comfpile::ContextKey] The context key of this artefact
attr_reader :context
attr_reader :exit_state attr_reader :exit_state
attr_reader :stage, :target attr_reader :stage, :target
@ -35,8 +32,6 @@ module Comfpile
# linking steps, but the objects can be built separately. # linking steps, but the objects can be built separately.
attr_reader :referenced_artefacts attr_reader :referenced_artefacts
attr_reader :build_dir
# ARTEFACT STATES # ARTEFACT STATES
# #
# The following states are known to the system: # The following states are known to the system:
@ -52,7 +47,7 @@ module Comfpile
# Meta-States exist: # Meta-States exist:
# - in_progress/completed: Anything but/Only succeeded, skipped, failed # - in_progress/completed: Anything but/Only succeeded, skipped, failed
def initialize(core, engine, stage, target, context, **opts) def initialize(core, engine, stage, target, **opts)
raise ArgumentError, "Unknown options supplied!" unless opts.empty? raise ArgumentError, "Unknown options supplied!" unless opts.empty?
@core = core @core = core
@ -60,7 +55,8 @@ module Comfpile
@stage = stage @stage = stage
@target = target @target = target
@context = @core.get_context_key context
@age = Time.at(0)
@parent_artefact = nil @parent_artefact = nil
@ -81,8 +77,6 @@ module Comfpile
@exit_state = nil @exit_state = nil
@running = false @running = false
@build_dir = opts[:build_dir] || @core.get_context_build_dir_path(self)
end end
def [](key) def [](key)
@ -116,7 +110,7 @@ module Comfpile
@log_current_line = text @log_current_line = text
@log_current_level = level @log_current_level = level
print "\033[2K> %-30s %s: %s\r" % [@stage, @target, text] puts "> %-30s %s:\n %s" % [@stage, @target, text]
nil nil
end end
@ -142,26 +136,26 @@ module Comfpile
}) })
end end
def parent_artefact(stage, target, context = @context) def parent_artefact(stage, target)
@parent_artefact = require_artefact(stage, target, context) @parent_artefact = require_artefact(stage, target)
end end
def include_artefact(stage, target, context = @context, **opts) def include_artefact(stage, target, **opts)
artefact = require_artefact(stage, target, context, **opts) artefact = require_artefact(stage, target, **opts)
@included_artefacts << artefact @included_artefacts << artefact
artefact artefact
end end
def require_artefact(stage, target, context = @context, **opts) def require_artefact(stage, target, **opts)
artefact = reference_artefact(stage, target, context, required: true, **opts) artefact = reference_artefact(stage, target, required: true, **opts)
@required_artefacts << artefact @required_artefacts << artefact
artefact artefact
end end
def reference_artefact(stage, target, context = @context, required: false) def reference_artefact(stage, target, required: false)
artefact = craft_artefact(stage, target, context) artefact = craft_artefact(stage, target)
wait_on(artefact) if required wait_on(artefact) if required
@ -213,12 +207,12 @@ module Comfpile
# found that can craft this, else returns the # found that can craft this, else returns the
# created or looked-up artefact. # created or looked-up artefact.
# #
def craft_artefact(stage, target, context = @context) def craft_artefact(stage, target)
@core.craft_artefact(stage, target, context) @core.craft_artefact(stage, target)
end end
def find_artefact(stage, target, context = @context) def find_artefact(stage, target)
@core.find_artefact(stage, target, context) @core.find_artefact(stage, target)
end end
def waitlist_empty? def waitlist_empty?

View file

@ -15,9 +15,7 @@ module Comfpile
@recipes = [] @recipes = []
end end
def craft(stage, target, context) def craft(stage, target)
context = @core.get_context_key context
@recipes.each do |recipe| @recipes.each do |recipe|
match = target match = target
@ -25,16 +23,16 @@ module Comfpile
next unless stage == recipe[:stage] next unless stage == recipe[:stage]
end end
if not (r = recipe[:regex]).nil? if r = recipe[:regex]
if r.is_a? String if r.is_a? String
next unless target == r next unless target == r
elsif r.is_a? Regexp else
match = r.match target match = r.match target
next if match.nil? next if match.nil?
end end
end end
new_artefact = Artefact.new(@core, self, stage, target, context) new_artefact = Artefact.new(@core, self, stage, target)
item = recipe[:block].call(match, new_artefact) item = recipe[:block].call(match, new_artefact)
@ -51,7 +49,7 @@ module Comfpile
other.subpriority <=> self.subpriority other.subpriority <=> self.subpriority
end end
def add_recipe(stage, target_regex = nil, &block) def add_recipe(stage = nil, target_regex, &block)
@recipes << { @recipes << {
regex: target_regex, regex: target_regex,
stage: stage, stage: stage,

View file

@ -1,156 +0,0 @@
module Comfpile
class ContextKey
attr_reader :provider, :context_hash, :context_symbol
def initialize(provider, ctx_hash, ctx_symbol)
@provider = provider
@context_hash = ctx_hash
@context_symbol = ctx_symbol
end
def to_s
"CTX[" + @context_symbol.to_s + "]"
end
end
#
# This class represents the configuration of a specific context.
# It has two main jobs:
# To provide functions to set up and merge configuration options
# from the various tags given to it, and
# to give reader options for the various config options.
#
# Most importantly, it contains mechanisms for safely setting up
# configurations and flagging issues.
#
class ContextConfig
attr_reader :context_tag
attr_reader :config_options
def initialize(context_tag, parent)
@context_tag = context_tag
@seeder_blocks = []
@config_options = nil
end
def add_seeder_block(priority, &block)
@seeder_blocks << {
priority: priority,
block: block
}
end
def resolve_key(key)
if key.is_a? Array
return key.map {|k| k.to_sym }
elsif key.is_a? String
return key.split('.').map {|k| k.to_sym }
elsif key.is_a? Symbol
return resolve_key(key.to_s)
end
end
def [](key)
@config_options&.dig(*resolve_key(key))
end
def []=(key, value)
key = resolve_key(key)
current_hash = (@config_options ||= {})
key[0..-2].each do |key|
current_hash = (current_hash[key] ||= {})
next if current_hash.is_a? Hash
raise ArgumentError, "Attempted to set child-parameter of another parameter!"
end
return @provider.provide_context(new_keys)
end
def to_s
"CTX[" + @context_symbol.to_s + "]"
end
alias inspect to_s
end
class ContextKeyProvider
def initialize
@known_context_keys = Hash.new
end
def symbol_to_keys(symbol)
raise ArgumentError, 'Input symbol needs to be a Symbol!' unless symbol.is_a? Symbol
out_keys = Hash.new
symbol.to_s.split(';').each do |key|
if key =~ /(?<key>[^=]+)=(?<value>[^=]+)/
out_keys[$~['key'].to_sym] = $~['value'].to_s
else
out_keys[key.to_sym] = true
end
end
out_keys
end
def sanitize_keys(keys)
out_keys = Hash.new
keys.each do |key, value|
if value.is_a? TrueClass
out_keys[key.to_sym] = true
elsif (not value.nil?) and (not value.is_a? FalseClass)
out_keys[key.to_sym] = value.to_s
end
end
out_keys
end
def keys_to_symbol(keys)
raise ArgumentError, 'Keys needs to be a Hash!' unless keys.is_a? Hash
keys.keys.sort.map do |key|
value = keys[key]
if value.is_a? TrueClass
key.to_s
elsif value.is_a? FalseClass
nil
else
"#{key}=#{value}"
end
end.compact.join(';').to_sym
end
def provide_context(ctx)
return ctx if ctx.is_a? ContextKey
orig_ctx = ctx
return @known_context_keys[ctx] if @known_context_keys.include? ctx
ctx = symbol_to_keys(ctx) if ctx.is_a? Symbol
ctx = sanitize_keys(ctx)
ctx_symbol = keys_to_symbol(ctx)
if @known_context_keys.include? ctx
existing_ctx = @known_context_keys[ctx]
@known_context_keys[orig_ctx] = existing_ctx
return existing_ctx
end
new_ctx = ContextKey.new(self, ctx, ctx_symbol)
@known_context_keys[ctx] = new_ctx
@known_context_keys[ctx_symbol] = new_ctx
end
end
end

View file

@ -1,17 +1,11 @@
require 'digest'
require_relative 'artefact_engine.rb' require_relative 'artefact_engine.rb'
require_relative 'context.rb'
module Comfpile module Comfpile
class Core class Core
attr_reader :processing_stack attr_reader :processing_stack
def initialize(build_dir_path: File.join('/tmp/comfpile/', Digest::MD5.hexdigest(Dir.pwd))) def initialize()
@build_dir_path = File.expand_path(build_dir_path)
@artefact_engines = [] @artefact_engines = []
@artefact_prio_counter = 0 @artefact_prio_counter = 0
@ -21,18 +15,10 @@ module Comfpile
# Stack-style processing queue for item processing # Stack-style processing queue for item processing
@processing_stack = [] @processing_stack = []
@context_key_provider = ContextKeyProvider.new()
end end
def get_context_key(key) def find_artefact(stage, file = :none)
return @context_key_provider.provide_context(key) @artefacts.dig(stage, file)
end
def find_artefact(stage, file = :none, context = :default)
context = get_context_key(context)
@artefacts.dig(context, stage, file)
end end
# Create or find a new artefact. # Create or find a new artefact.
@ -50,20 +36,17 @@ module Comfpile
# #
# @return [Comfpile::Artefact, nil] Found or created artefact, or nil if nothing could be done # @return [Comfpile::Artefact, nil] Found or created artefact, or nil if nothing could be done
# #
def craft_artefact(stage, file = :none, context = :default) def craft_artefact(stage, file = :none)
context = get_context_key(context) artefact = find_artefact(stage, file)
artefact = find_artefact(stage, file, context)
return artefact unless artefact.nil? return artefact unless artefact.nil?
@artefact_engines.each do |engine| @artefact_engines.each do |engine|
artefact = engine.craft stage, file, context artefact = engine.craft stage, file
if artefact if artefact
@artefacts[context] ||= {} @artefacts[stage] ||= {}
@artefacts[context][stage] ||= {} @artefacts[stage][file] = artefact
@artefacts[context][stage][file] = artefact
@processing_stack.push artefact @processing_stack.push artefact
@ -74,16 +57,13 @@ module Comfpile
nil nil
end end
def add_artefact(stage, file = :none, context = :default, engine: nil, artefact_class: Comfpile::Artefact) def add_artefact(stage, file = :none, engine: nil, artefact_class: Comfpile::Artefact)
context = get_context_key context return unless find_artefact(stage, file).nil?
return unless find_artefact(stage, file, context).nil? a = Artefact.new(self, engine, stage, file);
a = Artefact.new(self, engine, stage, file, context);
@artefacts[context] ||= {} @artefacts[stage] ||= {}
@artefacts[context][stage] ||= {} @artefacts[stage][file] = a
@artefacts[context][stage][file] = a
yield(a) if block_given? yield(a) if block_given?
@ -143,12 +123,6 @@ module Comfpile
nil nil
end end
def get_context_build_dir_path(context)
context = context.context if context.is_a? Artefact
File.expand_path(File.join(@build_dir_path, context.to_s))
end
def execute_step def execute_step
return if @processing_stack.empty? return if @processing_stack.empty?
# puts "Got #{@processing_stack.length} items..." # puts "Got #{@processing_stack.length} items..."
@ -161,14 +135,9 @@ module Comfpile
# puts "Processing artefact #{artefact.stage} #{artefact.target}" # puts "Processing artefact #{artefact.stage} #{artefact.target}"
build_path = get_context_build_dir_path(artefact) begin
FileUtils.mkpath build_path artefact.execute_step
rescue ArtefactExecSkipError
Dir.chdir build_path do
begin
artefact.execute_step
rescue ArtefactExecSkipError
end
end end
nil nil

View file

@ -25,9 +25,7 @@ module Comfpile
end end
@config_file_artefact = craft_artefact(:sourcefile, File.join(@target, "comf.yml")) @config_file_artefact = craft_artefact(:sourcefile, File.join(@target, "comf.yml"))
return if @config_file_artefact.nil? wait_on @config_file_artefact
wait_on @config_file_artefact
add_step do add_step do
unless @config_file_artefact.nil? unless @config_file_artefact.nil?
@ -63,10 +61,10 @@ module Comfpile
end end
def craft(stage, target, context) def craft(stage, target)
return unless stage == :config_file return unless stage == :config_file
ConfigArtefact.new(@core, self, stage, target, context) ConfigArtefact.new(@core, self, stage, target)
end end
end end
end end

View file

@ -6,23 +6,18 @@ module Comfpile
alias path filename alias path filename
alias file filename alias file filename
def initialize(*args, file: nil, **opts) def initialize(*args, file: filename, **opts)
super(*args, **opts) super(*args, **opts)
@original_filename = file @filename = file
unless File.exist? @original_filename unless File.exist? @filename
fail! "File could not be loaded!" fail! "File could not be loaded!"
return return
end end
@filename = @target # TODO add actual file reading/copying to build dir
add_step do
FileUtils.mkpath File.dirname(@filename)
FileUtils.cp @original_filename, @filename
end
end end
def mtime def mtime
@ -37,14 +32,14 @@ module Comfpile
@root_path = options[:root_path] @root_path = options[:root_path]
end end
def craft(stage, target, context) def craft(stage, target)
return nil unless stage == :sourcefile return nil unless stage == :sourcefile
full_path = File.expand_path(File.join(@root_path, target)) full_path = File.join(@root_path, target)
return nil unless File.exists? full_path return nil unless File.exists? full_path
FilesourceArtefact.new(@core, self, stage, target, context, FilesourceArtefact.new(@core, self, stage, target,
file: full_path); file: full_path);
end end
end end

View file

@ -117,7 +117,7 @@ module Comfpile
end end
def sourcefile_dependency_step def sourcefile_dependency_step
['include', 'require', 'reference'].each do |key| ['include', 'require', 'reference'].map do |key|
key_artefacts = resolve_sourcefile(find_parsed_parameters(key), optional: key == 'include') key_artefacts = resolve_sourcefile(find_parsed_parameters(key), optional: key == 'include')
@parsed_dependencies[key] = key_artefacts.map { |key| craft_artefact(:parsed, key) } @parsed_dependencies[key] = key_artefacts.map { |key| craft_artefact(:parsed, key) }
@ -205,28 +205,28 @@ module Comfpile
raise ArgumentError, "Missing regex parsing array!" unless @search_regexes.is_a? Array raise ArgumentError, "Missing regex parsing array!" unless @search_regexes.is_a? Array
end end
def generate_parser_artefact(stage, target, context) def generate_parser_artefact(stage, target)
match = @input_file_regex.match target match = @input_file_regex.match target
return nil if match.nil? return nil if match.nil?
ParserArtefact.new(@core, self, stage, target, context, ParserArtefact.new(@core, self, stage, target,
search_regexes: @search_regexes) search_regexes: @search_regexes)
end end
def generate_dependency_analysis_artefact(stage, target, context, **opts) def generate_dependency_analysis_artefact(stage, target, **opts)
match = @input_file_regex.match target match = @input_file_regex.match target
return nil if match.nil? return nil if match.nil?
DependencyAnalysisArtefact.new(@core, self, stage, target, context, **opts) DependencyAnalysisArtefact.new(@core, self, stage, target, **opts)
end end
def craft(stage, target, context) def craft(stage, target)
case stage case stage
when :parsed when :parsed
generate_parser_artefact(stage, target, context) generate_parser_artefact(stage, target)
when /^dependency_analysis(?:_(.+))?$/ when /^dependency_analysis(?:_(.+))?$/
traverse = $1&.split('_') traverse = $1&.split('_')
generate_dependency_analysis_artefact(stage, target, context, traverse: traverse) generate_dependency_analysis_artefact(stage, target, traverse: traverse)
else else
nil nil
end end

View file

@ -1,171 +0,0 @@
module Comfpile
class ContextTag
def initialize(tag)
@@known_tags ||= {}
case tag
when Symbol, String
precompiled = @@known_tags[tag.to_sym]
if not precompiled.nil?
@tag = precompiled[:tag]
@tag_array = precompiled[:array]
else
@tag_array = tag.to_s.split('_').uniq.sort
end
when Array
@tag_array = tag.map(&:to_s).uniq.sort
@tag = @tag_array
end
@tag ||= @tag_array.join('_').to_sym
tag_data = {
tag: @tag,
array: @ŧag_array
}
@@known_tags[@tag] ||= tag_data
@@known_tags[tag] ||= tag_data
end
def self.tagify(tag)
@known_tags ||= {}
end
end
#
# This class represents the configuration of a specific context.
# It has two main jobs:
# To provide functions to set up and merge configuration options
# from the various tags given to it, and
# to give reader options for the various config options.
#
# Most importantly, it contains mechanisms for safely setting up
# configurations and flagging issues.
#
class ContextConfig
attr_reader :context_tag
attr_reader :config_options
def initialize(context_tag, parent)
@context_tag = context_tag
@seeder_blocks = []
@config_options = nil
end
def add_seeder_block(priority, &block)
@seeder_blocks << {
priority: priority,
block: block
}
end
def resolve_key(key)
if key.is_a? Array
return key.map {|k| k.to_sym }
elsif key.is_a? String
return key.split('.').map {|k| k.to_sym }
elsif key.is_a? Symbol
return resolve_key(key.to_s)
end
end
def [](key)
@config_options&.dig(*resolve_key(key))
end
def []=(key, value)
key = resolve_key(key)
current_hash = (@config_options ||= {})
key[0..-2].each do |key|
current_hash = (current_hash[key] ||= {})
next if current_hash.is_a? Hash
raise ArgumentError, "Attempted to set child-parameter of another parameter!"
end
current_hash[key[-1]] = value
value
end
alias set []=
def set_flag(key, value)
set resolve_key(key).append(value), true
end
def get_flags(key)
(@config_options&.dig(*resolve_key(key)) || {}).keys
end
def dig(arg0, *args)
@config_options&.dig(arg0, *args)
end
def append(key, value)
key = resolve_key key
array = @config_options&.dig(*key)
if array.nil?
array = set key, []
end
raise ArgumentError, "Attempted to append to a non-list parameter!" unless array.is_a? Array
array << value
end
alias append_to append
def assert(orig_key, value)
key = resolve_key orig_key
current_value = @config_options&.dig(*key)
if current_value.nil?
set key, value
elsif current_value != value
raise ArgumentError, "Config key assertion failed! #{orig_key} should be #{value}, is #{current_value}!"
end
end
def build_config
@config_options = nil
@seeder_blocks.sort { |block| block[:priority] }.each do |block|
self.instance_exec(block, &block[:block])
end
self.freeze
end
end
class ContextConfigContainer
def initialize
@context_configs_seeds = []
end
def find_seeds_for(context_tag)
out = []
@context_configs_seeds.each do |seed|
seed_tags = seed[:context_tags]
seed_tags.each do |tag|
end
end
end
def add_to_config(context_config)
raise ArgumentError, "No context supplied!" unless context_config.is_a? ContextConfig
end
end
end

View file

@ -1,23 +0,0 @@
// Your First C++ Program
#include <iostream>
#include "main.h"
void print_bar() {
std::cout << "Bar";
}
#ifdef COMF_MAIN
int main() {
print_bar();
print_foo();
std::cout << "Hello World!";
return 0;
}
#endif

View file

@ -1,9 +0,0 @@
#pragma once
// comf.reference main.cpp
// comf.reference main2.cpp
void print_foo();
void print_bar();

View file

@ -1,22 +0,0 @@
// Your First C++ Program
#include <iostream>
#include "main.h"
void print_foo() {
std::cout << "Foo";
}
#ifdef COMF_MAIN
int main() {
print_foo();
print_bar();
std::cout << "Hello World!";
return 0;
}
#endif

View file

@ -0,0 +1,8 @@
#include "main.h"
#include <stdint.h>
int main() {
return 0;
}

View file

@ -0,0 +1,5 @@
#pragma once
#include "lib_test/test.h"

View file

@ -1 +0,0 @@
test: Hellooooo

View file

@ -1,108 +0,0 @@
-- comf.include: UQDS_specifics_pkg.vhd
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library uqdslib;
use uqdslib.UQDS_Specifics_pkg.all;
entity spi_master_tb is
end;
architecture bench of spi_master_tb is
-- Clock period
constant clk_period : time := 5 ns;
-- Generics
constant clkdiv : integer := 40;
constant clk_idle : std_logic := '1';
-- Ports
signal rst : std_logic := '0';
signal clk : std_logic;
signal data_tx : std_logic_vector(7 downto 0);
signal data_rx : std_logic_vector(7 downto 0);
signal send_request : std_logic;
signal byte_tx_complete : std_logic;
signal byte_rx_complete : std_logic;
signal pin_mosi : std_logic;
signal pin_miso : std_logic;
signal pin_clk : std_logic;
signal test_done : std_logic := '0';
begin
spi_master_inst : uqdslib.UQDS_Specifics_pkg.spi_master
generic map (
clkdiv => clkdiv,
clk_idle => clk_idle
)
port map (
rst => rst,
clk => clk,
spi_control_to.data_tx => data_tx,
spi_control_to.send_request => send_request,
spi_control_from.data_rx => data_rx,
spi_control_from.byte_tx_complete => byte_tx_complete,
spi_control_from.byte_rx_complete => byte_rx_complete,
pin_mosi => pin_mosi,
pin_miso => pin_miso,
pin_clk => pin_clk
);
pin_miso <= pin_mosi;
clk_process : process
begin
clk <= '1';
wait for clk_period/2;
clk <= '0';
wait for clk_period/2;
if(test_done) then wait; end if;
end process clk_process;
data_process : process
begin
rst <= '1';
wait for 100 ns;
rst <= '0';
for i in 0 to 4 loop
data_tx <= std_logic_vector(to_unsigned(i, data_tx'length));
send_request <= '1';
wait until falling_edge(byte_tx_complete) for 1 ms;
send_request <= '0';
end loop;
for i in 0 to 4 loop
data_tx <= std_logic_vector(to_unsigned(i, data_tx'length));
send_request <= '1';
wait until falling_edge(byte_tx_complete) for 1 ms;
send_request <= '0';
wait for 1.5 us;
end loop;
data_tx <= std_logic_vector(to_unsigned(69, data_tx'length));
send_request <= '1';
wait until falling_edge(byte_tx_complete) for 1 ms;
send_request <= '0';
wait for 400 ns;
rst <= '1';
wait for 100 ns;
rst <= '0';
wait for 3 us;
test_done <= '1';
wait until falling_edge(byte_rx_complete) for 1 us;
wait;
end process data_process;
end;