Skip to content

Reference

This part of the documentation focuses on an information-oriented approach. Use it as a reference for the technical implementation of the ASHES project code.

fpaa_compile(funcName)

Returns the verilog code after conversion.

The entry function of the system-level compiler.

Source code in ashes_fg/fpaa/new_converter.py
def fpaa_compile(funcName):
	"""
	Returns the verilog code after conversion.

	The entry function of the system-level compiler.
	"""
	global v_code, inout_module_list, module_v_code_list
	inout_module_list = []
	module_v_code_list = []
	v_code = ""
	try:
		func = inspect.getsource(funcName)
	except TypeError:
		with open(funcName, 'r') as f:
			func = f.read()
	if "flag_std_lib." in func:
		func = func.replace("flag_std_lib.", "fg.")
	root = ast.parse(func)
	print("PARSED MODULE\n\n")
	print(ast.dump(root))
	print("END PARSED MODULE\n\n")
	m = parse_py(root)
	v_code += "module %s();\n" % (m.mod_name)
	construct_in_out_module(m)
	construct_module(m)
	v_code += "endmodule\n"
	for i in module_v_code_list:
		v_code += i
	v_code += '\n'
	print("V code is... \n\n")
	print(v_code)
	return v_code

module_parse(node, mod)

Source code in ashes_fg/fpaa/new_converter.py
def module_parse(node, mod):
	"""
	"""
	for lib in custom_import:
		exec(lib)
	code = ast.unparse(node)
	if isinstance(node, ast.Assign):
		target = ast.unparse(node.targets)
		# deal with none fg situation
		if 'nmirror_w_bias' in code:
			mod.submod[target] = fg.nmirror_w_bias(target)
			mod.executedVariable.append('%s=\'%s\'' % (target, target))
			add_net(target)

			return mod
		if "fg." not in code:  # not a object to convert to verilog
			if isinstance(node.value, ast.List):
				# this is to construct input list
				proess_list_value(mod, ast.unparse(node.targets),
								  node.value.elts)
				t_exec = target + '=' + str(mod.submod[target])
				mod.executedVariable.append(t_exec)
			return mod
		# else:
		#     mod.executedVariable.append('%s=\'%s\'' % (target, target))
		# prepare target and already executed context
		for c in mod.executedVariable:
			exec(c)
		exec(code)
		# solve vector
		try:
			mod.vec_slice[target] = [
				ast.unparse(node.value.args[0].slice.upper),
				ast.unparse(node.value.args[0].slice.lower)
			]
			exec('%s.input=%s' % (target, node.value.args[0].value.id))

		except BaseException:
			pass
		if re.findall(in_out_re, code):  # find in_out_module
			mod.in_out_submod[target] = eval(target)
			mod.submod[target] = eval(target)
		else:  # regular modules
			tar_ins = eval(target)
			if isinstance(tar_ins, list):
				all_net = []
				for i in node.targets[0].elts:
					mod.executedVariable.append('%s=\'%s\'' % (i.id, i.id))
					all_net.append(add_net(i.id))
				mod.submod[target] = tar_ins[0]
				st.net_table[target] = all_net

			else:
				mod.submod[target] = tar_ins
				add_net(target)
		if isinstance(eval(target), list):
			pass
		else:
			mod.executedVariable.append('%s=\'%s\'' % (target, target))
	elif isinstance(node, ast.Return):
		pass
	return mod

parse_py(node)

Takes a Python-style HDL circuit description and translates it into an intermediate Verilog netlist. This function walks the AST (abstract syntax tree) of the Python HDL file recursively, thereby allowing a top-level circuit to contain many subcircuits. The recursion continues until a node that is a function definition is passed; in ASHES' Python HDL, a function definition is where the circuit elements are actually istantiated and connected, which is why the base case executes module_parse().

Parameters:

Name Type Description Default
node Module | FunctionDef

An AST node produced by Python's ast parser.

required
  • If of type ast.Module: node is the entire Python HDL file (top-level circuit container).
  • If of type ast.FunctionDef: node is a function that contains circuit instantiations and connections.

Returns:

Name Type Description
module_ast module_ast

An object representing the parsed Verilog module. Contains the module's name, ports, instances, and connectivity extracted from the Python HDL.

Source code in ashes_fg/fpaa/new_converter.py
def parse_py(node: ast.Module | ast.FunctionDef) -> table_class.module_ast:
	"""Takes a Python-style HDL circuit description and translates it into an 
	intermediate Verilog netlist. This function walks the AST (abstract syntax 
	tree) of the Python HDL file recursively, thereby allowing a top-level 
	circuit to contain many subcircuits. The recursion continues until a node 
	that is a function definition is passed; in ASHES' Python HDL, a function 
	definition is where the circuit elements are actually istantiated and 
	connected, which is why the base case executes `module_parse()`.

	Args:
		node: An AST node produced by Python's `ast` parser.
        - If of type `ast.Module`: `node` is the entire Python HDL file (top-level circuit container).
        - If of type `ast.FunctionDef`: `node` is a function that contains circuit instantiations and connections.

	Returns:
		module_ast: An object representing the parsed Verilog module. Contains the module's name, ports, instances, and connectivity extracted from the Python HDL.
	"""
	print("start parsing")
	if isinstance(node, ast.Module):
		for b in node.body:
			print(ast.dump(b))
			print("\n")
			mod_obj = parse_py(b)
		return mod_obj
	if isinstance(node, ast.FunctionDef):
		mod_obj = table_class.module_ast(node.name, board_type="FPAA")
		for b in node.body:
			mod_obj = module_parse(b, mod_obj)
			print("mod_obj after module_parse in FunctionDef:\n\n", vars(mod_obj))
		return mod_obj