[myhdl-list] More thoughts and code towards dynamic code generation
Brought to you by:
jandecaluwe
From: Samuele D. <sm...@gm...> - 2016-05-01 21:22:33
|
Hello, Finally I have some contributions to the project: After seeing some questions about VHDL "generate" like capabilities for MyHDL I started thinking about a solution. It is only a proof of concept, let me know your thoughts! The following code uses RedBaron to inspect and refactor itself in order to generate an elif statement list. A decorator is used for targeting the function to analyze: from myhdl import * from functools import wraps import inspect from redbaron import RedBaron i_redbaron = [i for i in range(2,6)] def redBaronGenerate(i_redbaron): def real_redBaronGenerate(func): with open(inspect.getsourcefile(func), "r") as source_file: red = RedBaron(source_file.read()) #find the decoratornode and the definition node (parent of the former) node = red.find("decorator", lambda x: x.value.value.name.value == "redBaronGenerate") defnode = node.parent #delete the decorator del defnode.decorators[node.index_on_parent] #search elif elifnode = defnode.find("elif") #iterate for elif insertions as desired start =elifnode.index_on_parent for i,elifindex in zip(i_redbaron , range(start,start+len(i_redbaron))): # prepare the elif template elifnodetemplate = elifnode.copy() for node in elifnodetemplate.findAll("name","i_redbaron"): node.replace(str(i)) #insert the node elifnode.parent.value.insert(elifindex,elifnodetemplate) #delete the template del elifnode.parent.value[elifnode.index_on_parent] #we dump the result to a file as a demonstration purpose #we could try also to substitute the function with the newer at runtime with open("address_gens_redbaron.py", "w") as source_file: source_file.write(red.dumps()) @wraps(func) def wrapper(*args, **kwds): return func(*args, **kwds) return wrapper return real_redBaronGenerate @block def address_gens(clk,count,datain_address,feedback_address): n = len(count) @always(clk.posedge) def address_counter(): count.next = count +1 @always(clk.posedge) def datain_address_generator(): datain_address.next = concat(count[n-2:0],count[n-2],count[n-1]) @always(clk.posedge) @redBaronGenerate(i_redbaron) def feedback_address_generator(): #REDBARON for i_redbaron in range(1,5) if count[n-1] == 0: feedback_address.next = concat(count[n:n-1],count[n-2:1],count[n-2],count[0]) elif count[n-i_redbaron] == 0: feedback_address.next = concat(count[n:n-i_redbaron],count[n-i_redbaron-1:1], count[n-i_redbaron-1],count[0]) else: feedback_address.next = count #and last 2 values are not important (actually one could be used to do half of the last butterfly) return address_counter,datain_address_generator,feedback_address_generator if __name__ == "__main__": @block def ClkDriver(clk,halfperiod): @always(delay(halfperiod)) def driveClk(): clk.next = not clk return driveClk @block def tb(clk,count,dina,fa): clk_driver = ClkDriver(clk,5) a_gen = address_gens(clk,count,dina,fa) return clk_driver,a_gen clk = Signal(False) count = Signal(modbv(0,_nrbits=8)) dina = Signal(intbv(0,_nrbits=8)) fa = Signal(intbv(0,_nrbits=8)) #address_gens(clk,count,fa).convert(hdl='Verilog') tb1 = tb(clk,count,dina,fa) tb1.config_sim(trace=True) |