pytholite/compiler: recognize composite I/O pattern
authorSebastien Bourdeauducq <sebastien@milkymist.org>
Sun, 11 Nov 2012 17:03:16 +0000 (18:03 +0100)
committerSebastien Bourdeauducq <sebastien@milkymist.org>
Sun, 11 Nov 2012 17:03:16 +0000 (18:03 +0100)
migen/pytholite/compiler.py
migen/pytholite/io.py

index 660719c06a942626609410ceca8c4cc8a1964498..5ba96e9a6af30a1df625af867833f3a3fc3d7cb2 100644 (file)
@@ -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
@@ -148,7 +154,52 @@ class _Compiler:
                                else:
                                        raise NotImplementedError
                else:
-                       raise NotImplementedError
+                       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)
index 3d875e3a43fd0543aa778ce682bfa2147e2bf357..2dfbf7710eef01ad501710b266ce589da1bda395 100644 (file)
@@ -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 [], []