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