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
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
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
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
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