require 'active_support/concern' module Origen # Include this module to identify it as a top-level object in Origen, normally # an object that represents the SoC/Top-level device. # # Origen will then fallback on this top-level object to service any register # read/write requests or any pin requests that are generated by lower # level objects and which cannot be fulfilled at that level. # # The current top level object can then be referenced at any time via # Origen.top_level. module TopLevel extend ActiveSupport::Concern included do # Any pattern compilation or other operation that requires access to a pinmap # will look for it via this attribute, this should return a path to the pinmap # file to be used attr_accessor :pinmap # Store the current pattern compiler instance name attr_accessor :compiler include Origen::Model end # Unloads all modules class defined by the application and reloads the target, use # this in the console to pick up changes made to files since you opened it. # It will only work if your application uses Origen auto-loading from the app/dir, # any files that you have manually required will not be re-loaded and may generally # cause problems with the use of this method. def reload! Loader.unload Origen.app.reload_target! true end # Top-level timing manager/API, returns an instance of Origen::Pins::Timing def timing @timing ||= Pins::Timing.new end def reset! reset bang: true end def pinmap=(val) @pinmap = Pathname.new(val) end def reset(options = {}) Origen.app.listeners_for(:before_top_level_reset).each(&:before_top_level_reset) if options[:bang] Origen.app.listeners_for(:shutdown, top_level: :last).each do |listener| listener.shutdown(Pattern.create_options) end Origen.app.listeners_for(:on_top_level_reset!, top_level: false).each(&:on_top_level_reset!) end Origen.app.listeners_for(:on_top_level_reset, top_level: false).each(&:on_top_level_reset) Origen.app.listeners_for(:reset_registers).each(&:reset_registers) if options[:bang] Origen.app.listeners_for(:startup).each do |listener| listener.startup(Pattern.create_options) end end Origen.app.listeners_for(:after_top_level_reset).each(&:after_top_level_reset) end def ip_name @ip_name || self.class.to_s.split('::').last.symbolize end # Use this to specify the current package option for the given SoC. # # This allows different pin configurations to be specified by package. def current_package=(val) @current_package_id = case val when ChipPackage val.id else packages.include?(val) ? val : nil end end alias_method :package=, :current_package= # Returns the current package configuration of the pin owner, unless specifically # specified by the application this will return nil. def current_package(_options = {}) if @current_package_id return _packages[@current_package_id] if _packages[@current_package_id] fail "The package #{@current_package_id} of #{self.class} has not been defined!" end end alias_method :package, :current_package # Returns an array containing the IDs of all known configurations if no ID is supplied, # otherwise returns an object representing the given package ID def packages(id = nil, _options = {}) id, options = nil, id if id.is_a?(Hash) if id _packages[id] else _packages.ids end end # Execute the supplied block within the context of the given package, at the end # the model's package attribute will be restored to what it was before calling # this method. def with_package(id, _options = {}) orig = package self.package = id yield self.package = orig end def add_package(id, _options = {}) p = ChipPackage.new p.id = id p.owner = self yield p if block_given? _add_package(p) p end def includes_origen_top_level? true end # Sets the Origen.top_level.packages array to nil. Written so packages created in memory can # be erased so packages defined in Ruby files can be loaded def delete_all_packages @_packages = nil end alias_method :delete_all_pkgs, :delete_all_packages private def init_top_level Origen.app.add_toplevel_listener(self) end def _packages @_packages ||= {} end def _add_package(package) if _packages[package.id] fail "There is already a package called #{package.id}!" else _packages[package.id] = package end end end end