pytholite/io: support token pull
authorSebastien Bourdeauducq <sebastien@milkymist.org>
Fri, 16 Nov 2012 22:48:41 +0000 (23:48 +0100)
committerSebastien Bourdeauducq <sebastien@milkymist.org>
Fri, 16 Nov 2012 22:48:41 +0000 (23:48 +0100)
migen/pytholite/compiler.py
migen/pytholite/expr.py
migen/pytholite/io.py

index ec5c41d1f18e663f6009e0ae46ac35e0a22bba04..269706a462336477102b10a8e04d5f61c0400c2b 100644 (file)
@@ -154,7 +154,7 @@ class _Compiler:
                                        raise NotImplementedError
                        from_model.append((tregs, fstatement.value))
                
-               states, exit_states = gen_io(self, model, args, from_model)
+               states, exit_states = gen_io(self, modelname, model, args, from_model)
                sa.assemble(states, exit_states)
                return fstatement
        
@@ -222,7 +222,7 @@ class _Compiler:
                        if not isinstance(yvalue, ast.Call) or not isinstance(yvalue.func, ast.Name):
                                raise NotImplementedError("Unrecognized I/O pattern")
                        callee = self.symdict[yvalue.func.id]
-                       states, exit_states = gen_io(self, callee, yvalue.args, [])
+                       states, exit_states = gen_io(self, None, callee, yvalue.args, [])
                        sa.assemble(states, exit_states)
                else:
                        raise NotImplementedError
index 8c1c355118570a7b2848c69f577132d78d1e9f9a..bd82781d87d72ec9ae224464c9bbc95b2c713d08 100644 (file)
@@ -19,6 +19,10 @@ class ExprCompiler:
                        return self.visit_expr_name(node)
                elif isinstance(node, ast.Num):
                        return self.visit_expr_num(node)
+               elif isinstance(node, ast.Attribute):
+                       return self.visit_expr_attribute(node)
+               elif isinstance(node, ast.Subscript):
+                       return self.visit_expr_subscript(node)
                else:
                        raise NotImplementedError
        
@@ -102,3 +106,10 @@ class ExprCompiler:
        
        def visit_expr_num(self, node):
                return Constant(node.n)
+       
+       def visit_expr_attribute(self, node):
+               raise NotImplementedError
+       
+       def visit_expr_subscript(self, node):
+               raise NotImplementedError
+       
index f0be3ca3108a22ceb91e13598b76aa8466309a03..51820a69cd738eb7073feb7befa6d3d4fda0536f 100644 (file)
@@ -4,6 +4,7 @@ from migen.fhdl.structure import *
 from migen.flow.actor import *
 from migen.actorlib.sim import *
 from migen.pytholite.fsm import *
+from migen.pytholite.expr import ExprCompiler
 
 class Pytholite:
        def get_fragment(self):
@@ -18,7 +19,28 @@ def make_io_object(dataflow=None):
        else:
                return DFPytholite(*dataflow)
 
-def gen_df_io(compiler, to_model, from_model):
+class _TokenPullExprCompiler(ExprCompiler):
+       def __init__(self, symdict, modelname, ep):
+               super().__init__(symdict)
+               self.modelname = modelname
+               self.ep = ep
+       
+       def visit_expr_subscript(self, node):
+               # check that we are subscripting <modelname>.value
+               if not isinstance(node.value, ast.Attribute) \
+                 or node.value.attr != "value" \
+                 or not isinstance(node.value.value, ast.Name) \
+                 or node.value.value.id != self.modelname:
+                       raise NotImplementedError
+               
+               if not isinstance(node.slice, ast.Index):
+                       raise NotImplementedError
+               field = ast.literal_eval(node.slice.value)
+               signal = getattr(self.ep.token, field)
+               
+               return signal
+
+def gen_df_io(compiler, modelname, to_model, from_model):
        if len(to_model) == 1 or len(to_model) == 2:
                epname = ast.literal_eval(to_model[0])
                ep = compiler.ioo.endpoints[epname]
@@ -27,9 +49,22 @@ def gen_df_io(compiler, to_model, from_model):
        
        if len(to_model) == 1:
                # token pull from sink
-               raise NotImplementedError # TODO
+               if not isinstance(ep, Sink):
+                       raise TypeError("Attempted to pull from source")
+               ec = _TokenPullExprCompiler(compiler.symdict, modelname, ep)
+               state = []
+               for target_regs, expr in from_model:
+                       cexpr = ec.visit_expr(expr)
+                       state += [reg.load(cexpr) for reg in target_regs]
+               state += [
+                       ep.ack.eq(1),
+                       If(~ep.stb, AbstractNextState(state))
+               ]
+               return [state], [state]
        else:
                # token push to source
+               if not isinstance(ep, Source):
+                       raise TypeError("Attempted to push to sink")
                if from_model:
                        raise TypeError("Attempted to read from pushed token")
                d = to_model[1]
@@ -46,8 +81,8 @@ def gen_df_io(compiler, to_model, from_model):
                ]
                return [state], [state]
 
-def gen_io(compiler, model, to_model, from_model):
+def gen_io(compiler, modelname, model, to_model, from_model):
        if model == Token:
-               return gen_df_io(compiler, to_model, from_model)
+               return gen_df_io(compiler, modelname, to_model, from_model)
        else:
                raise NotImplementedError