def test_add_migen(self):
        test_template1 = NodeTemplate(name="test_1",
                                      inputs=[('a', DOptional(int)),
                                              ('b', DOptional(int))])

        test_template1.add_constructor(AMigenNode2())

        with DeltaGraph():
            n1 = test_template1.call(2, 3)

        self.assertEqual(len(n1.bodies), 1)
        self.assertIn(PyMigenBody, n1.body.access_tags)
    def test_via_migen_init(self):

        m_template = NodeTemplate(name="MTemplate",
                                  inputs=[('a', DOptional(int)),
                                          ('b', DOptional(int))])

        @DeltaBlock(m_template, allow_const=False)
        def m_simple_add(a: DOptional(int), b: DOptional(int)):
            raise DeltaRuntimeExit

        m_maker = AMigenNode(node_template=m_template)
        with DeltaGraph():
            n1 = m_maker.call(a=1, b=3)
        self.assertEqual(len(n1.bodies), 2)
        self.assertIn(PyMigenBody, n1.body.access_tags)
Example #3
0
    def setUp(self):
        # obligatory and optional ports
        out_port_obl = OutPort(
            NamespacedName("port_name", None),
            DInt(),
            InPort(NamespacedName("port_name", None),
                   DInt(), None, 0),
            None
        )
        out_port_opt = OutPort(
            NamespacedName("port_name", None),
            DInt(),
            InPort(NamespacedName("port_name", None),
                   DOptional(DInt()), None, 0),
            None
        )

        # 4 types of queues
        self.delta_queue_obl = DeltaQueue(out_port_obl)
        self.delta_queue_opt = DeltaQueue(out_port_opt)
        self.const_queue_obl = ConstQueue(out_port_obl)
        self.const_queue_opt = ConstQueue(out_port_opt)

        # test messages
        self.msg1 = QueueMessage(1)
        self.msg2 = QueueMessage(2)
        self.msg_with_none = QueueMessage(None)
        self.msg_unpackable = QueueMessage("abcde")

        # these messages should be received
        self.msg1_answer = QueueMessage(1)
        self.msg2_answer = QueueMessage(2)
        self.msg_with_none_answer = QueueMessage(None)
Example #4
0
    def test_add_migen(self):
        test_template1 = NodeTemplate(name="test_1",
                                      inputs=[('a', DOptional(int)),
                                              ('b', DOptional(int))])

        class AMigenNode(MigenNodeTemplate):
            def migen_body(self, template):
                template.add_pa_in_port('a', DOptional(int))
                template.add_pa_in_port('b', DOptional(int))

        with DeltaGraph():
            n1 = test_template1.call(a=2, b=3)

        self.assertEqual(len(n1.bodies), 0)
        n1.add_body(AMigenNode())
        self.assertEqual(len(n1.bodies), 1)
        self.assertIn(PyMigenBody, n1.body.access_tags)
Example #5
0
 def test_in_port_capnp_optional(self):
     """Generate optional in port."""
     in_port = InPort(NamespacedName("node_name", "index"), DOptional(int),
                      None, 0)
     capnp_in_port = dotdf_capnp.InPort.new_message()
     in_port.capnp(capnp_in_port)
     self.assertEqual(capnp_in_port.name, "index")
     self.assertEqual(dill.loads(capnp_in_port.type), DInt())
     self.assertEqual(capnp_in_port.optional, True)
    def migen_body(self, template):
        # Input/Outputs start here:

        # 2 inputs and 2 outputs.
        #
        # This block group ports which will be accessed by migen, using
        # the protocol adapters.
        # in_ports and out_ports implement a similar logic based on 3
        # signals, ready, valid and data.
        # An input can be received when the ready signal is = '1'.
        # data contains the value of the message that we are receiving
        # and can considered sensible only when valid = '1', i.e. when
        # a new data has been received on the pa_input_port.
        # The opposite logic holds true for the outputs.
        in1 = template.add_pa_in_port('in1', DOptional(int))
        in2 = template.add_pa_in_port('in2', DOptional(int))
        out1 = template.add_pa_out_port('out1', int)
        out2 = template.add_pa_out_port('out2', int)

        # The main migen logic starts here:

        # Everything below is just an example that show different routines.

        # Add a 32-bit counter (0-2**32-1) which will increment at each clock
        # cycle.
        self.counter = migen.Signal(32)
        self.sync += self.counter.eq(self.counter + 1)

        # Add a condition when in_ports are ready.
        self.comb += migen.If(self.counter >= 3, in1.ready.eq(1),
                              in2.ready.eq(1))

        # Pretend that we do a useful calculations.
        # Here we first check that the outputs are ready.
        # Then wait for the counter to reach 100.
        # And write outputs.
        # Note that the output should be marked as valid.
        self.comb += migen.If(
            (out1.ready & out2.ready) == 1,
            migen.If(self.counter == 5, out1.data.eq(in1.data + in2.data),
                     out2.data.eq(self.counter),
                     out1.valid.eq(in1.valid & in2.valid),
                     out2.valid.eq(in1.valid & in2.valid)).Else(
                         out1.valid.eq(0), out2.valid.eq(0)))
Example #7
0
    def migen_body(self, template):
        # inputs and 1 output
        in1 = template.add_pa_in_port('in1', DOptional(int))
        out1 = template.add_pa_out_port('out1', DOptional(int))

        # Counter
        self.incremented = migen.Signal(10)

        # for instance, at this clock the node is ready to input
        self.comb += in1.ready.eq(1)

        self.sync += migen.If(
            out1.ready == 1,
            migen.If(in1.valid,
                     out1.data.eq(self.incremented),
                     out1.valid.eq(0x1),
                     self.incremented.eq(in1.data+1)
                     ).Else(out1.valid.eq(0))
        )
    def test_inputs_enforced_optional(self):
        """Test to ensure in params must match when associating
        constructors with a NodeTemplate
        """
        test_template2 = NodeTemplate(name="test",
                                      inputs=[('a', DOptional(int)),
                                              ('b', DOptional(int))],
                                      outputs=int)

        with self.assertRaises(ValueError):

            @DeltaBlock(test_template2, allow_const=False)
            def _test1(a: DOptional(int), b: int) -> int:
                return a + b

        with self.assertRaises(ValueError):

            @DeltaBlock(test_template2, allow_const=False)
            def _test2(wrong_name: int, b: int) -> int:
                return wrong_name + b
Example #9
0
    def test_node_serialisation_multi_body_node(self):
        """If two blocks share the same body only keep one copy."""
        with DeltaGraph() as test_graph:
            n1 = self.func(2, 3)

        @DeltaBlock(allow_const=False)
        def over_complex_add(a: DOptional(int), b: DOptional(int)):
            raise DeltaRuntimeExit

        @Interactive(inputs=[('a', DOptional(int)), ('b', DOptional(int))])
        def broken_adder(node: RealNode):
            node.receive('a')
            node.receive('b')
            raise DeltaRuntimeExit

        n1.add_body(AMigenNode())
        n1.add_body(over_complex_add)
        n1.add_body(OpCacher().cached_add)
        n1.add_body(broken_adder)

        _, prog = serialize_graph(test_graph)

        self.assertEqual(len(prog.nodes[2].bodies), 5)
    def migen_body(self, template):
        start = template.add_pa_in_port('start', DOptional(int))
        out_a = template.add_pa_out_port('out_a', int)
        out_b = template.add_pa_out_port('out_b', int)
        # This will need to be converted to boolean when migen nodes support
        # boolean
        self.cnt = migen.Signal(10)

        self.comb += (out_a.ready.eq(1), out_b.ready.eq(1), start.ready.eq(1))
        self.sync += migen.If(self.cnt & 0x1, out_a.valid.eq(start.data),
                              out_b.valid.eq(0)).Else(
                                  out_a.valid.eq(0),
                                  out_b.valid.eq(start.data))
        self.sync += (self.cnt.eq(self.cnt + 1), out_a.data.eq(self.cnt),
                      out_b.data.eq(self.cnt))
Example #11
0
    def migen_body(self, template):

        inp = template.add_pa_in_port('inp', DOptional(DInt()))
        trigger = template.add_pa_in_port('trigger', DOptional(DInt()))
        out = template.add_pa_out_port('out', DInt())

        # Declare input and output ports always happy to receive/transmit data
        self.comb += (
            inp.ready.eq(1),
            trigger.ready.eq(1),
            out.ready.eq(1),
        )

        commander_fsm = FSM(reset_state="IDLE")
        self.submodules.commander_fsm = commander_fsm

        commander_fsm.act("IDLE", If(inp.valid == 1, NextState("LOADING")))

        commander_fsm.act(
            "LOADING",
            If(trigger.valid & trigger.data == 1, NextState("RETURN")).Else(
                NextValue(out.data, out.data + inp.data), ))

        commander_fsm.act("RETURN", NextValue(out.valid, 1), NextState("IDLE"))
Example #12
0
 def cached_add(self, a: DOptional(int), b: DOptional(int)):
     if (a, b) not in self._add_cache:
         self._add_cache[(a, b)] = a + b
     raise DeltaRuntimeExit
Example #13
0
 def test_DOptional(self):
     port = OutPort(NamespacedName("test_name", None), DOptional(DInt()),
                    None, None)
     with self.assertRaises(TypeError):
         dummy = port.port_type
Example #14
0
 def test_DOptiona_of_DUnion(self):
     port = InPort(NamespacedName("test_name", None),
                   DOptional(DUnion([DInt(), DFloat()])), None, 0)
     self.assertEqual(port.port_type, DUnion([DInt(), DFloat()]))
     self.assertEqual(port.is_optional, True)
Example #15
0
 def test_DOptional(self):
     port = InPort(NamespacedName("test_name", None), DOptional(DInt()),
                   None, 0)
     self.assertEqual(port.port_type, DInt())
     self.assertEqual(port.is_optional, True)
Example #16
0
def add(a: int, b: DOptional(int)) -> int:
    if b is None:
        return a
    else:
        return a + b
 def _test1(a: DOptional(int), b: int) -> int:
     return a + b
Example #18
0
 def migen_body(self, template):
     template.add_pa_in_port('a', DOptional(int))
     template.add_pa_in_port('b', DOptional(int))
Example #19
0
 def add_print_exit(a: DOptional(int), b: DOptional(int)) -> Void:
     print(a + b)
     raise DeltaRuntimeExit
Example #20
0
 def simple_add_2(a: DOptional(int), b: DOptional(int)):
     raise DeltaRuntimeExit
Example #21
0
 def over_complex_add(a: DOptional(int), b: DOptional(int)):
     raise DeltaRuntimeExit