Hello,

I'm trying to write a simple DSL to define memory maps of hardware
devices.
Something like:

cfg_block "top_device", :depth => 16 do
  reg "ctrl_reg", :offset => 0, :mode => "RW"
  reg "status_reg", :offset => 1, :mode => "R"
end

I've implemented something but I am not satisfied with it.

The problem I have is about scoping.  How can I make the reg command
in my
small DSL exemple above execute in the context of the object created
by the
cfg_block method?  The way I implemented this is by passing the
created
cfg_block object as a block parameter and then passing it to every reg
command.  E.g:

cfg_block "top_device", :depth => 16 do |__dev__|
   reg "ctrl_reg",   __dev__,     :offset...
end

I consider this redundant since I'd like the context to provide the
cfg_block reference.  I tried multiple things but haven't figured it
out
using blocks.  Is there a way to get rid of __dev__?

Suggestions would be greatly appreciated.    Thanks in advance.

My implementation follows below:

module Register_defs

   class Cfg_Block < Hash

      def initialize(name, params={})
         self[:name] = name
         self[:regs] = {}
         self.merge!(params)
      end

      def add_reg(reg)
         self[:regs][reg[:name]] = reg
      end

   end

   class Register < Hash
      def initialize(name, cfg_block, params={})
         self[:name] = name
         self.merge!(params)
         cfg_block.add_reg(self)
      end

   end

   def cfg_block(name, params={})
      cfg_block = Cfg_Block.new(name, params)
      yield(cfg_block)
      cfg_block
   end

   def reg(name, cfg_block, params={})
      reg = Register.new(name, cfg_block, params)
      yield(reg)
      reg
   end

end

include Register_defs

modules =  cfg_block "top_block" do |cb|

   reg "reg1", cb, :addr => 0 do
      # do something
   end

   reg "reg2", cb, :addr => 0 do
      # do something else
   end

end

p modules