2012-11-11 17:48:23 -05:00
|
|
|
import ast
|
|
|
|
|
|
|
|
from migen.fhdl.structure import *
|
2012-11-23 15:20:18 -05:00
|
|
|
from migen.fhdl.structure import _Slice
|
2012-11-11 17:48:23 -05:00
|
|
|
from migen.pytholite import transel
|
|
|
|
from migen.pytholite.reg import *
|
2013-06-28 13:03:55 -04:00
|
|
|
from migen.pytholite.util import eval_ast
|
2012-11-11 17:48:23 -05:00
|
|
|
|
|
|
|
class ExprCompiler:
|
|
|
|
def __init__(self, symdict):
|
|
|
|
self.symdict = symdict
|
2014-10-17 05:08:37 -04:00
|
|
|
|
2012-11-11 17:48:23 -05:00
|
|
|
def visit_expr(self, node):
|
2013-07-27 09:38:29 -04:00
|
|
|
# Attempt compile-time evaluation first
|
|
|
|
try:
|
|
|
|
result = eval_ast(node, self.symdict)
|
|
|
|
except:
|
|
|
|
result = None
|
|
|
|
if isinstance(result, int):
|
|
|
|
return result
|
|
|
|
|
2012-11-11 17:48:23 -05:00
|
|
|
if isinstance(node, ast.Call):
|
|
|
|
return self.visit_expr_call(node)
|
|
|
|
elif isinstance(node, ast.BinOp):
|
|
|
|
return self.visit_expr_binop(node)
|
|
|
|
elif isinstance(node, ast.Compare):
|
|
|
|
return self.visit_expr_compare(node)
|
|
|
|
elif isinstance(node, ast.Name):
|
|
|
|
return self.visit_expr_name(node)
|
|
|
|
elif isinstance(node, ast.Num):
|
|
|
|
return self.visit_expr_num(node)
|
2012-11-16 17:48:41 -05:00
|
|
|
elif isinstance(node, ast.Attribute):
|
|
|
|
return self.visit_expr_attribute(node)
|
|
|
|
elif isinstance(node, ast.Subscript):
|
|
|
|
return self.visit_expr_subscript(node)
|
2012-11-11 17:48:23 -05:00
|
|
|
else:
|
|
|
|
raise NotImplementedError
|
2014-10-17 05:08:37 -04:00
|
|
|
|
2012-11-11 17:48:23 -05:00
|
|
|
def visit_expr_call(self, node):
|
|
|
|
if isinstance(node.func, ast.Name):
|
|
|
|
callee = self.symdict[node.func.id]
|
|
|
|
else:
|
|
|
|
raise NotImplementedError
|
|
|
|
if callee == transel.bitslice:
|
|
|
|
if len(node.args) != 2 and len(node.args) != 3:
|
|
|
|
raise TypeError("bitslice() takes 2 or 3 arguments")
|
|
|
|
val = self.visit_expr(node.args[0])
|
2013-06-28 13:03:55 -04:00
|
|
|
low = eval_ast(node.args[1], self.symdict)
|
2012-11-11 17:48:23 -05:00
|
|
|
if len(node.args) == 3:
|
2013-06-28 13:03:55 -04:00
|
|
|
up = eval_ast(node.args[2], self.symdict)
|
2012-11-11 17:48:23 -05:00
|
|
|
else:
|
|
|
|
up = low + 1
|
|
|
|
return _Slice(val, low, up)
|
|
|
|
else:
|
|
|
|
raise NotImplementedError
|
2014-10-17 05:08:37 -04:00
|
|
|
|
2012-11-11 17:48:23 -05:00
|
|
|
def visit_expr_binop(self, node):
|
|
|
|
left = self.visit_expr(node.left)
|
|
|
|
right = self.visit_expr(node.right)
|
|
|
|
if isinstance(node.op, ast.Add):
|
|
|
|
return left + right
|
|
|
|
elif isinstance(node.op, ast.Sub):
|
|
|
|
return left - right
|
|
|
|
elif isinstance(node.op, ast.Mult):
|
|
|
|
return left * right
|
|
|
|
elif isinstance(node.op, ast.LShift):
|
|
|
|
return left << right
|
|
|
|
elif isinstance(node.op, ast.RShift):
|
|
|
|
return left >> right
|
|
|
|
elif isinstance(node.op, ast.BitOr):
|
|
|
|
return left | right
|
|
|
|
elif isinstance(node.op, ast.BitXor):
|
|
|
|
return left ^ right
|
|
|
|
elif isinstance(node.op, ast.BitAnd):
|
|
|
|
return left & right
|
|
|
|
else:
|
|
|
|
raise NotImplementedError
|
2014-10-17 05:08:37 -04:00
|
|
|
|
2012-11-11 17:48:23 -05:00
|
|
|
def visit_expr_compare(self, node):
|
|
|
|
test = self.visit_expr(node.left)
|
|
|
|
r = None
|
|
|
|
for op, rcomparator in zip(node.ops, node.comparators):
|
|
|
|
comparator = self.visit_expr(rcomparator)
|
|
|
|
if isinstance(op, ast.Eq):
|
|
|
|
comparison = test == comparator
|
|
|
|
elif isinstance(op, ast.NotEq):
|
|
|
|
comparison = test != comparator
|
|
|
|
elif isinstance(op, ast.Lt):
|
|
|
|
comparison = test < comparator
|
|
|
|
elif isinstance(op, ast.LtE):
|
|
|
|
comparison = test <= comparator
|
|
|
|
elif isinstance(op, ast.Gt):
|
|
|
|
comparison = test > comparator
|
|
|
|
elif isinstance(op, ast.GtE):
|
|
|
|
comparison = test >= comparator
|
|
|
|
else:
|
|
|
|
raise NotImplementedError
|
|
|
|
if r is None:
|
|
|
|
r = comparison
|
|
|
|
else:
|
|
|
|
r = r & comparison
|
|
|
|
test = comparator
|
|
|
|
return r
|
2014-10-17 05:08:37 -04:00
|
|
|
|
2012-11-11 17:48:23 -05:00
|
|
|
def visit_expr_name(self, node):
|
|
|
|
if node.id == "True":
|
2012-11-28 17:18:43 -05:00
|
|
|
return 1
|
2012-11-11 17:48:23 -05:00
|
|
|
if node.id == "False":
|
2012-11-28 17:18:43 -05:00
|
|
|
return 0
|
2012-11-11 17:48:23 -05:00
|
|
|
r = self.symdict[node.id]
|
|
|
|
if isinstance(r, ImplRegister):
|
|
|
|
r = r.storage
|
|
|
|
return r
|
2014-10-17 05:08:37 -04:00
|
|
|
|
2012-11-11 17:48:23 -05:00
|
|
|
def visit_expr_num(self, node):
|
2012-11-28 17:18:43 -05:00
|
|
|
return node.n
|
2014-10-17 05:08:37 -04:00
|
|
|
|
2012-11-16 17:48:41 -05:00
|
|
|
def visit_expr_attribute(self, node):
|
|
|
|
raise NotImplementedError
|
2014-10-17 05:08:37 -04:00
|
|
|
|
2012-11-16 17:48:41 -05:00
|
|
|
def visit_expr_subscript(self, node):
|
|
|
|
raise NotImplementedError
|