mirror of
https://github.com/enjoy-digital/litex.git
synced 2025-01-04 09:52:26 -05:00
pytholite/compiler: recognize composite I/O pattern
This commit is contained in:
parent
0b5652bb79
commit
f59fd69e34
2 changed files with 58 additions and 3 deletions
|
@ -57,6 +57,12 @@ class _Register:
|
|||
sync = [Case(self.sel, *cases)]
|
||||
return Fragment(sync=sync)
|
||||
|
||||
def _is_name_used(node, name):
|
||||
for n in ast.walk(node):
|
||||
if isinstance(n, ast.Name) and n.id == name:
|
||||
return True
|
||||
return False
|
||||
|
||||
class _Compiler:
|
||||
def __init__(self, ioo, symdict, registers):
|
||||
self.ioo = ioo
|
||||
|
@ -147,8 +153,53 @@ class _Compiler:
|
|||
self.symdict[target.id] = reg
|
||||
else:
|
||||
raise NotImplementedError
|
||||
else:
|
||||
return self.visit_io_pattern(sa, node.targets, callee, value.args, statements)
|
||||
|
||||
def visit_io_pattern(self, sa, targets, model, args, statements):
|
||||
# first statement is <modelname> = <model>(<args>)
|
||||
if len(targets) != 1 or not isinstance(targets[0], ast.Name):
|
||||
raise NotImplementedError("Unrecognized I/O pattern")
|
||||
modelname = targets[0].id
|
||||
if modelname in self.symdict:
|
||||
raise NotImplementedError("I/O model name is not free")
|
||||
|
||||
# second statement must be yield <modelname>
|
||||
try:
|
||||
ystatement = next(statements)
|
||||
except StopIteration:
|
||||
raise NotImplementedError("Incomplete or fragmented I/O pattern")
|
||||
if not isinstance(ystatement, ast.Expr) \
|
||||
or not isinstance(ystatement.value, ast.Yield) \
|
||||
or not isinstance(ystatement.value.value, ast.Name) \
|
||||
or ystatement.value.value.id != modelname:
|
||||
raise NotImplementedError("Unrecognized I/O pattern")
|
||||
|
||||
# following optional statements are assignments to registers
|
||||
# with <modelname> used in expressions.
|
||||
from_model = []
|
||||
while True:
|
||||
try:
|
||||
fstatement = next(statements)
|
||||
except StopIteration:
|
||||
fstatement = None
|
||||
if not isinstance(fstatement, ast.Assign) \
|
||||
or not _is_name_used(fstatement.value, modelname):
|
||||
break
|
||||
tregs = []
|
||||
for target in fstatement.targets:
|
||||
if isinstance(target, ast.Attribute) and target.attr == "store":
|
||||
if isinstance(target.value, ast.Name):
|
||||
tregs.append(self.symdict[target.value.id])
|
||||
else:
|
||||
raise NotImplementedError
|
||||
else:
|
||||
raise NotImplementedError
|
||||
from_model.append((tregs, fstatement.value))
|
||||
|
||||
states, exit_states = gen_io(self, model, args, from_model)
|
||||
sa.assemble(states, exit_states)
|
||||
return fstatement
|
||||
|
||||
def visit_if(self, sa, node):
|
||||
test = self.visit_expr(node.test)
|
||||
|
@ -212,7 +263,7 @@ class _Compiler:
|
|||
if isinstance(node.value, ast.Yield):
|
||||
yvalue = node.value.value
|
||||
if not isinstance(yvalue, ast.Call) or not isinstance(yvalue.func, ast.Name):
|
||||
raise NotImplementedError("Unrecognized I/O sequence")
|
||||
raise NotImplementedError("Unrecognized I/O pattern")
|
||||
callee = self.symdict[yvalue.func.id]
|
||||
states, exit_states = gen_io(self, callee, yvalue.args, [])
|
||||
sa.assemble(states, exit_states)
|
||||
|
|
|
@ -18,7 +18,11 @@ def make_io_object(dataflow=None):
|
|||
|
||||
|
||||
def gen_io(compiler, model, to_model, from_model):
|
||||
print(model)
|
||||
print("model: " + str(model))
|
||||
print("to_model:")
|
||||
for arg in to_model:
|
||||
print(ast.dump(arg))
|
||||
print("from_model:")
|
||||
for target, expr in from_model:
|
||||
print(str(target) + " <= " + ast.dump(expr))
|
||||
return [], []
|
||||
|
|
Loading…
Reference in a new issue