import pytest

from b_asic import SFG, Input, Output, Constant, Register, ConstantMultiplication


@pytest.fixture
def sfg_two_inputs_two_outputs():
    """Valid SFG with two inputs and two outputs.
	     .               .
    in1-------+  +--------->out1
         .    |  |       .
         .    v  |       .
         .   add1+--+    .
         .    ^     |    .
         .    |     v    .
    in2+------+    add2---->out2
       | .          ^    .
       | .          |    .
       +------------+    .
	     .               .
    out1 = in1 + in2
	out2 = in1 + 2 * in2
    """
    in1 = Input()
    in2 = Input()
    add1 = in1 + in2
    add2 = add1 + in2
    out1 = Output(add1)
    out2 = Output(add2)
    return SFG(inputs = [in1, in2], outputs = [out1, out2])

@pytest.fixture
def sfg_nested():
    """Valid SFG with two inputs and one output.
    out1 = in1 + (in1 + in1 * in2) * (in1 + in2 * (in1 + in1 * in2))
    """
    mac_in1 = Input()
    mac_in2 = Input()
    mac_in3 = Input()
    mac_out1 = Output(mac_in1 + mac_in2 * mac_in3)
    MAC = SFG(inputs = [mac_in1, mac_in2, mac_in3], outputs = [mac_out1])

    in1 = Input()
    in2 = Input()
    mac1 = MAC(in1, in1, in2)
    mac2 = MAC(in1, in2, mac1)
    mac3 = MAC(in1, mac1, mac2)
    out1 = Output(mac3)
    return SFG(inputs = [in1, in2], outputs = [out1])

@pytest.fixture
def sfg_delay():
    """Valid SFG with one input and one output.
    out1 = in1'
    """
    in1 = Input()
    reg1 = Register(in1)
    out1 = Output(reg1)
    return SFG(inputs = [in1], outputs = [out1])

@pytest.fixture
def sfg_accumulator():
    """Valid SFG with two inputs and one output.
    data_out = (data_in' + data_in) * (1 - reset)
    """
    data_in = Input()
    reset = Input()
    reg = Register()
    reg.input(0).connect((reg + data_in) * (1 - reset))
    data_out = Output(reg)
    return SFG(inputs = [data_in, reset], outputs = [data_out])

@pytest.fixture
def simple_filter():
    """A valid SFG that is used as a filter in the first lab for TSTE87.
                +----<constmul1----+
                |                  |
                |                  |
    in1>------add1>------reg>------+------out1>
    """
    in1 = Input()
    reg = Register()
    constmul1 = ConstantMultiplication(0.5)
    add1 = in1 + constmul1
    reg.input(0).connect(add1)
    constmul1.input(0).connect(reg)
    out1 = Output(reg)
    return SFG(inputs=[in1], outputs=[out1])