def test_move_scalar_add_past_matmul():
    top_in = oh.make_tensor_value_info("top_in", TensorProto.FLOAT, [1, 2])
    add_param = oh.make_tensor_value_info("add_param", TensorProto.FLOAT, [1, 1])
    matmul_param = oh.make_tensor_value_info("matmul_param", TensorProto.FLOAT, [2, 2])
    top_out = oh.make_tensor_value_info("top_out", TensorProto.FLOAT, [1, 2])
    modelproto = oh.make_model(
        oh.make_graph(
            name="test",
            inputs=[top_in],
            outputs=[top_out],
            value_info=[add_param, matmul_param],
            nodes=[
                oh.make_node("Add", ["top_in", "add_param"], ["middle"]),
                oh.make_node("MatMul", ["middle", "matmul_param"], ["top_out"]),
            ],
        )
    )
    model = ModelWrapper(modelproto)
    model = model.transform(InferShapes())
    model.set_initializer("add_param", np.asarray([[3]], dtype=np.float32))
    model.set_initializer(
        "matmul_param", np.asarray([[2, 4], [-1, 1]], dtype=np.float32)
    )
    new_model = model.transform(MoveScalarAddPastMatMul())
    inp_dict = {"top_in": np.asarray([[-1.0, 1.0]], dtype=np.float32)}
    assert ox.compare_execution(model, new_model, inp_dict)
    assert new_model.graph.node[0].op_type == "MatMul"
    assert new_model.graph.node[1].op_type == "Add"
    assert new_model.graph.node[0].output[0] == new_model.graph.node[1].input[0]
示例#2
0
def make_modelwrapper(C, pe, idt, odt, pdt, func, vecs):
    NumChannels = C.shape[0]

    inp = helper.make_tensor_value_info("inp", TensorProto.FLOAT, vecs + [NumChannels])
    outp = helper.make_tensor_value_info(
        "outp", TensorProto.FLOAT, vecs + [NumChannels]
    )

    node_inp_list = ["inp", "const"]

    node = helper.make_node(
        "ChannelwiseOp_Batch",
        node_inp_list,
        ["outp"],
        domain="finn.custom_op.fpgadataflow",
        backend="fpgadataflow",
        NumChannels=NumChannels,
        Func=func,
        PE=pe,
        inputDataType=idt.name,
        outputDataType=odt.name,
        paramDataType=pdt.name,
        numInputVectors=vecs,
    )
    graph = helper.make_graph(nodes=[node], name="graph", inputs=[inp], outputs=[outp])

    model = helper.make_model(graph, producer_name="model")
    model = ModelWrapper(model)

    model.set_tensor_datatype("inp", idt)
    model.set_tensor_datatype("outp", odt)

    model.set_tensor_datatype("const", idt)
    model.set_initializer("const", C)
    return model
示例#3
0
def test_xnorpopcountmatmul():
    M = 1
    K = 3
    N = 3
    x = helper.make_tensor_value_info("x", TensorProto.FLOAT, [M, K])
    W = helper.make_tensor_value_info("W", TensorProto.FLOAT, [K, N])
    out = helper.make_tensor_value_info("out", TensorProto.FLOAT, ["x", "y"])
    node_def = helper.make_node("XnorPopcountMatMul", ["x", "W"], ["out"],
                                domain="finn.custom_op.general")
    modelproto = helper.make_model(
        helper.make_graph([node_def], "test_model", [x], [out],
                          value_info=[W]))
    model = ModelWrapper(modelproto)
    model.set_tensor_datatype("x", DataType.BINARY)
    model.set_tensor_datatype("W", DataType.BINARY)
    W_data = np.asarray([[1, 0, 0], [0, 1, 0], [0, 0, 1]], dtype=np.float32)
    model.set_initializer("W", W_data)
    # test shape inference
    model = model.transform(InferShapes())
    assert model.get_tensor_shape("out") == [M, N]
    # test datatype inference
    assert model.get_tensor_datatype("out") is DataType.FLOAT32
    model = model.transform(InferDataTypes())
    assert model.get_tensor_datatype("out") is DataType.UINT32
    # test execution
    x_data = np.asarray([[1, 0, 0]], dtype=np.float32)
    inp_dict = {"x": x_data}
    out_dict = oxe.execute_onnx(model, inp_dict)
    Wb = 2 * W_data - 1
    xb = 2 * x_data - 1
    rb = np.matmul(xb, Wb)
    assert (2 * out_dict["out"] - K == rb).all()
示例#4
0
def _make_single_vvau_modelwrapper(
    W, pe, k_h, k_w, channels, dim_h, dim_w, wdt, idt, odt, T=None, tdt=None
):
    in_shape = [1, dim_h, dim_w, k_h * k_w * channels]  # [N, H, W, K*K*CH]
    out_shape = [
        1,
        dim_h,
        dim_w,
        channels,
    ]  # [N, H, W, OFM_CH] (OFM_CH=IFM_CH because depthwise convolution)

    inp = helper.make_tensor_value_info("inp", TensorProto.FLOAT, in_shape)
    outp = helper.make_tensor_value_info("outp", TensorProto.FLOAT, out_shape)

    if T is not None:
        no_act = 0
        node_inp_list = ["inp", "weights", "thresh"]
        actval = odt.min()
    else:
        no_act = 1
        node_inp_list = ["inp", "weights"]
        actval = 0

    VVAU_node = helper.make_node(
        "Vector_Vector_Activate_Batch",
        node_inp_list,
        ["outp"],
        domain="finn.custom_op.fpgadataflow",
        backend="fpgadataflow",
        PE=pe,
        Dim=[dim_h, dim_w],
        Channels=channels,
        Kernel=[k_h, k_w],
        resType="lut",
        ActVal=actval,
        inputDataType=idt.name,
        weightDataType=wdt.name,
        outputDataType=odt.name,
        noActivation=no_act,
    )

    graph = helper.make_graph(
        nodes=[VVAU_node], name="vvau_graph", inputs=[inp], outputs=[outp]
    )

    model = helper.make_model(graph, producer_name="vvau-model")
    model = ModelWrapper(model)

    model.set_tensor_datatype("inp", idt)
    model.set_tensor_datatype("outp", odt)
    model.set_tensor_datatype("weights", wdt)

    model.set_initializer("weights", W)
    model.set_tensor_shape("weights", (channels, 1, k_h, k_w))

    if T is not None:
        model.set_tensor_datatype("thresh", tdt)
        model.set_initializer("thresh", T)

    return model
def test_move_chw_add_past_conv(idim, k, s, ich, och):
    odim = compute_conv_output_dim(idim, k, s)

    ishape = [1, ich, idim, idim]
    oshape = [1, och, odim, odim]
    add_param_shape = [1, ich, 1, 1]
    conv_param_shape = [och, ich, k, k]

    inp = helper.make_tensor_value_info("inp", TensorProto.FLOAT, ishape)
    outp = helper.make_tensor_value_info("outp", TensorProto.FLOAT, oshape)
    a0 = helper.make_tensor_value_info("a0", TensorProto.FLOAT,
                                       add_param_shape)
    a1 = helper.make_tensor_value_info("a1", TensorProto.FLOAT,
                                       conv_param_shape)

    conv_config = {}
    conv_config["dilations"] = [1, 1]
    conv_config["group"] = 1
    conv_config["kernel_shape"] = [k, k]
    conv_config["pads"] = [0, 0, 0, 0]
    conv_config["strides"] = [s, s]

    add_node = helper.make_node("Add", ["inp", "a0"], ["add_out"])
    conv_node = helper.make_node("Conv", ["add_out", "a1"], ["outp"],
                                 **conv_config)

    model = helper.make_model(
        helper.make_graph(
            nodes=[add_node, conv_node],
            name="move-add-graph",
            inputs=[inp],
            outputs=[outp],
            value_info=[a0, a1],
        ))

    model = ModelWrapper(model)
    # initialize model
    a0_values = np.random.uniform(
        low=0, high=1, size=tuple(add_param_shape)).astype(np.float32)
    model.set_initializer("a0", a0_values)
    a1_values = np.random.uniform(
        low=0, high=1, size=tuple(conv_param_shape)).astype(np.float32)
    model.set_initializer("a1", a1_values)

    model = model.transform(InferShapes())

    # execution before transformation
    inp_values = np.random.uniform(low=0, high=1,
                                   size=tuple(ishape)).astype(np.float32)
    idict = {model.graph.input[0].name: inp_values}
    odict = oxe.execute_onnx(model, idict)
    y_before = odict[model.graph.output[0].name]

    model = model.transform(MoveAddPastConv())
    odict = oxe.execute_onnx(model, idict)
    y_after = odict[model.graph.output[0].name]

    assert np.isclose(y_before, y_after).all()
    assert model.graph.node[0].op_type == "Conv"
    assert model.graph.node[1].op_type == "Add"
示例#6
0
def test_modelwrapper():
    lfc = get_test_model_trained("LFC", 1, 1)
    bo.export_finn_onnx(lfc, (1, 1, 28, 28), export_onnx_path)
    model = ModelWrapper(export_onnx_path)
    assert model.check_all_tensor_shapes_specified() is False
    inp_name = model.graph.input[0].name
    inp_shape = model.get_tensor_shape(inp_name)
    assert inp_shape == [1, 1, 28, 28]
    # find first matmul node
    l0_mat_tensor_name = ""
    l0_inp_tensor_name = ""
    for node in model.graph.node:
        if node.op_type == "MatMul":
            l0_inp_tensor_name = node.input[0]
            l0_mat_tensor_name = node.input[1]
            break
    assert l0_mat_tensor_name != ""
    l0_weights = model.get_initializer(l0_mat_tensor_name)
    assert l0_weights.shape == (784, 1024)
    l0_weights_hist = Counter(l0_weights.flatten())
    assert (l0_weights_hist[1.0] + l0_weights_hist[-1.0]) == 784 * 1024
    l0_weights_rand = np.random.randn(784, 1024)
    model.set_initializer(l0_mat_tensor_name, l0_weights_rand)
    assert (model.get_initializer(l0_mat_tensor_name) == l0_weights_rand).all()
    assert l0_inp_tensor_name != ""
    inp_cons = model.find_consumer(l0_inp_tensor_name)
    assert inp_cons.op_type == "MatMul"
    out_prod = model.find_producer(l0_inp_tensor_name)
    assert out_prod.op_type == "Sign"
    os.remove(export_onnx_path)
示例#7
0
def make_lookup_model(embeddings, ishape, idt, edt):
    num_embeddings, embedding_dim = embeddings.shape

    class LookupModel(nn.Module):
        def __init__(self, num_embeddings, embedding_dim):
            super().__init__()
            self.lookup = nn.Embedding(
                num_embeddings=num_embeddings, embedding_dim=embedding_dim
            )

        def forward(self, x):
            x = self.lookup(x)
            return x

    torch_model = LookupModel(num_embeddings, embedding_dim)
    input_t = torch.zeros(ishape, dtype=torch.int64)
    ret = FINNManager.export(torch_model, input_t=input_t, opset_version=11)
    model = ModelWrapper(ret)
    iname = model.graph.input[0].name
    ename = model.graph.node[0].input[0]
    model.set_tensor_datatype(iname, idt)
    eshape = model.get_tensor_shape(ename)
    assert tuple(eshape) == embeddings.shape
    model.set_initializer(ename, embeddings)
    model.set_tensor_datatype(ename, edt)
    model = model.transform(InferShapes())
    model = model.transform(InferDataTypes())
    return model
示例#8
0
def test_round_thresholds():
    v = helper.make_tensor_value_info("v", TensorProto.FLOAT, [1, 4])
    thresholds = helper.make_tensor_value_info("thresholds", TensorProto.FLOAT,
                                               [4, 1])
    out = helper.make_tensor_value_info("out", TensorProto.FLOAT, [1, 4])
    node_def = helper.make_node("MultiThreshold", ["v", "thresholds"], ["out"],
                                domain="finn")
    graph_def = helper.make_graph([node_def], "test_model", [v, thresholds],
                                  [out])
    model_def = helper.make_model(graph_def)
    model = ModelWrapper(model_def)
    threshold_val = np.asarray([[-1.1], [0.7], [2.3], [5.1]], dtype=np.float32)
    model.set_initializer("thresholds", threshold_val)
    model.set_tensor_datatype("v", DataType.INT8)
    inp_dict_f = {"v": np.floor(threshold_val).T}
    inp_dict_n = {"v": np.round(threshold_val).T}
    inp_dict_c = {"v": np.ceil(threshold_val).T}
    orig_f = oxe.execute_onnx(model, inp_dict_f)["out"]
    orig_n = oxe.execute_onnx(model, inp_dict_n)["out"]
    orig_c = oxe.execute_onnx(model, inp_dict_c)["out"]
    assert model.get_tensor_datatype("thresholds") == DataType.FLOAT32
    new_model = model.transform(RoundAndClipThresholds())
    # rounded up thresholds should have same dtype as input
    assert new_model.get_tensor_datatype("thresholds") == DataType.INT8
    new_f = oxe.execute_onnx(new_model, inp_dict_f)["out"]
    new_n = oxe.execute_onnx(new_model, inp_dict_n)["out"]
    new_c = oxe.execute_onnx(new_model, inp_dict_c)["out"]
    assert np.isclose(orig_f, new_f, atol=1e-3).all()
    assert np.isclose(orig_n, new_n, atol=1e-3).all()
    assert np.isclose(orig_c, new_c, atol=1e-3).all()
示例#9
0
def test_move_add_past_mul_multi():
    top_in = oh.make_tensor_value_info("top_in", TensorProto.FLOAT, [2])
    add_param_0 = oh.make_tensor_value_info("add_param_0", TensorProto.FLOAT, [2])
    mul_param_0 = oh.make_tensor_value_info("mul_param_0", TensorProto.FLOAT, [2])
    add_param_1 = oh.make_tensor_value_info("add_param_1", TensorProto.FLOAT, [2])
    mul_param_1 = oh.make_tensor_value_info("mul_param_1", TensorProto.FLOAT, [2])
    top_out = oh.make_tensor_value_info("top_out", TensorProto.FLOAT, [2])
    modelproto = oh.make_model(
        oh.make_graph(
            name="test",
            inputs=[top_in],
            outputs=[top_out],
            value_info=[add_param_0, mul_param_0, add_param_1, mul_param_1],
            nodes=[
                oh.make_node("Add", ["top_in", "add_param_0"], ["middle_0"]),
                oh.make_node("Mul", ["middle_0", "mul_param_0"], ["middle_1"]),
                oh.make_node("Add", ["middle_1", "add_param_1"], ["middle_2"]),
                oh.make_node("Mul", ["middle_2", "mul_param_1"], ["top_out"]),
            ],
        )
    )
    model = ModelWrapper(modelproto)
    model = model.transform(InferShapes())
    model.set_initializer("add_param_0", np.asarray([1, 3], dtype=np.float32))
    model.set_initializer("mul_param_0", np.asarray([2, 4], dtype=np.float32))
    model.set_initializer("add_param_1", np.asarray([-1, 3], dtype=np.float32))
    model.set_initializer("mul_param_1", np.asarray([2, -4], dtype=np.float32))
    new_model = model.transform(MoveAddPastMul())
    inp_dict = {"top_in": np.asarray([-1.0, 1.0], dtype=np.float32)}
    assert ox.compare_execution(model, new_model, inp_dict)
示例#10
0
def test_conv_lowering_conv_1x1():

    np.random.seed(0)

    in_feature_dim_h = 7
    in_feature_dim_w = 7
    in_chn = 3
    kernel_size = 1
    out_feature_dim_h = in_feature_dim_h
    out_feature_dim_w = in_feature_dim_w

    input_shape = [1, in_chn, in_feature_dim_h, in_feature_dim_w]
    output_shape = [1, in_chn, out_feature_dim_h, out_feature_dim_w]

    conv_param_shape = [in_chn, in_chn, kernel_size, kernel_size]

    conv_config = {}
    conv_config["dilations"] = [1, 1]
    conv_config["group"] = 1
    conv_config["kernel_shape"] = [kernel_size, kernel_size]
    conv_config["pads"] = [0, 0, 0, 0]
    conv_config["strides"] = [1, 1]

    top_in = oh.make_tensor_value_info("top_in", TensorProto.FLOAT,
                                       input_shape)
    top_out = oh.make_tensor_value_info("top_out", TensorProto.FLOAT,
                                        output_shape)

    value_info = [
        oh.make_tensor_value_info("p1", TensorProto.FLOAT, conv_param_shape)
    ]

    modelproto = oh.make_model(
        oh.make_graph(
            name="test",
            inputs=[top_in],
            outputs=[top_out],
            value_info=value_info,
            nodes=[
                oh.make_node("Conv", ["top_in", "p1"], ["top_out"],
                             **conv_config)
            ],
        ))
    model = ModelWrapper(modelproto)
    model = model.transform(InferShapes())
    model.set_initializer("p1",
                          np.random.rand(*conv_param_shape).astype(np.float32))

    new_model = model.transform(LowerConvsToMatMul())
    inp_dict = {"top_in": np.random.rand(*input_shape).astype(np.float32)}

    assert oxe.compare_execution(model, new_model, inp_dict)
    assert new_model.graph.node[0].op_type == "Transpose"
    assert new_model.graph.node[1].op_type == "MatMul"
    assert new_model.graph.node[2].op_type == "Transpose"
    assert len(new_model.graph.node) == 3
示例#11
0
def test_infer_shapes():
    # load the onnx model
    raw_m = get_data("finn.data", "onnx/mnist-conv/model.onnx")
    model = ModelWrapper(raw_m)
    graph = model.graph

    # multi-thresholding node to be inserted between the first Relu and MaxPool node

    # get Relu node to use data
    Relu_node = graph.node[3]
    assert Relu_node.op_type == "Relu", "The wrong model was chosen for the check"

    # create thresholds tensor as constant
    mt_thresh0 = helper.make_tensor_value_info("mt_thresh0", TensorProto.FLOAT,
                                               [8, 7])

    # random numbers for the thresholds
    # thresholds for one channel have to be sorted to guarantee the correct behavior
    mt_thresh0_values = np.empty([8, 7], dtype=np.float32)
    for i in range(len(mt_thresh0_values)):
        mt_thresh0_values[i] = np.sort(np.random.random_sample(7) * 10)

    model.set_initializer(mt_thresh0.name, mt_thresh0_values)

    # add multi-thresholding node and change Relu node
    mt_node = helper.make_node(
        "MultiThreshold",
        ["mt_v0", "mt_thresh0"],
        [Relu_node.output[0]],
        domain="finn.custom_op.general",
    )
    Relu_node.output[0] = "mt_v0"

    # explicitly remove any present shape from ReLU and MultiThreshold outputs
    util.remove_by_name(model.graph.value_info, Relu_node.output[0])
    util.remove_by_name(model.graph.value_info, mt_node.output[0])
    graph.node.insert(4, mt_node)

    # first check routine
    # check if at least one shape is not specified
    assert not (
        model.check_all_tensor_shapes_specified()
    ), "All tensors are already specified before the shape inference execution"

    # perform shape inference on mixed model
    model = model.transform(InferShapes())

    # second check routine
    # now all shapes should be specified and mt_node output shape is (1,8,28,28)
    assert (model.check_all_tensor_shapes_specified()
            ), "There are still tensors that are not specified"
    assert (model.get_tensor_shape(mt_node.output[0])) == ([
        1, 8, 28, 28
    ]), "output of multi-thresholding node has wrong shape"
示例#12
0
def create_one_fc_model(mem_mode="const"):
    # create a model with a StreamingFCLayer instance with no activation
    # the wider range of the full accumulator makes debugging a bit easier
    wdt = DataType.INT2
    idt = DataType.INT32
    odt = DataType.INT32
    m = 4
    no_act = 1
    binary_xnor_mode = 0
    actval = 0
    simd = 4
    pe = 4

    inp = helper.make_tensor_value_info("inp", TensorProto.FLOAT, [1, m])
    outp = helper.make_tensor_value_info("outp", TensorProto.FLOAT, [1, m])

    fc0 = helper.make_node(
        "StreamingFCLayer_Batch",
        ["inp", "w0"],
        ["outp"],
        domain="finn",
        backend="fpgadataflow",
        resType="ap_resource_lut()",
        MW=m,
        MH=m,
        SIMD=simd,
        PE=pe,
        inputDataType=idt.name,
        weightDataType=wdt.name,
        outputDataType=odt.name,
        ActVal=actval,
        binaryXnorMode=binary_xnor_mode,
        noActivation=no_act,
        mem_mode=mem_mode,
    )

    graph = helper.make_graph(nodes=[fc0],
                              name="fclayer_graph",
                              inputs=[inp],
                              outputs=[outp])

    model = helper.make_model(graph, producer_name="fclayer-model")
    model = ModelWrapper(model)

    model.set_tensor_datatype("inp", idt)
    model.set_tensor_datatype("outp", odt)
    model.set_tensor_datatype("w0", wdt)

    # generate weights
    w0 = np.eye(m, dtype=np.float32)
    model.set_initializer("w0", w0)

    model = model.transform(CreateDataflowPartition())
    return model
示例#13
0
def test_depthwise_conv_lowering(idt, k, ifm_dim, ifm_ch, stride, padding):
    wdt = idt
    odt = DataType.INT32
    ofm_ch = ifm_ch
    ofm_dim = compute_conv_output_dim(ifm_dim, k, stride, pad=padding[0])

    # set up onnx model
    inp = oh.make_tensor_value_info("inp", TensorProto.FLOAT,
                                    [1, ifm_ch, ifm_dim, ifm_dim])
    outp = oh.make_tensor_value_info("outp", TensorProto.FLOAT,
                                     [1, ofm_ch, ofm_dim, ofm_dim])

    W = oh.make_tensor_value_info("W", TensorProto.FLOAT, [ofm_ch, 1, k, k])

    dw_cnv = oh.make_node(
        "Conv",
        inputs=["inp", "W"],
        outputs=["outp"],
        kernel_shape=[k, k],
        pads=padding,
        strides=[stride, stride],
        group=ifm_ch,
    )
    graph = oh.make_graph(
        nodes=[dw_cnv],
        name="dw_cnv_graph",
        inputs=[inp],
        outputs=[outp],
        value_info=[W],
    )

    model = oh.make_model(graph, producer_name="dws_cnv-model")
    model = ModelWrapper(model)
    model.set_tensor_datatype("inp", idt)
    model.set_tensor_datatype("outp", odt)
    model.set_tensor_datatype("W", wdt)
    w_tensor = gen_finn_dt_tensor(wdt, [ofm_ch, 1, k, k])
    model.set_initializer("W", w_tensor)
    model = model.transform(InferShapes())

    input_tensor = gen_finn_dt_tensor(idt, [1, ifm_ch, ifm_dim, ifm_dim])
    input_dict = {"inp": input_tensor}
    output_dict = oxe.execute_onnx(model, input_dict)
    expected = output_dict["outp"]

    model = model.transform(LowerConvsToMatMul())
    output_dict = oxe.execute_onnx(model, input_dict)
    produced = output_dict["outp"]
    assert (produced == expected).all()

    # check if created nodes have attributes that indicate depthwise conv
    assert model.get_tensor_sparsity("W") is not None
    im2col_node = getCustomOp(model.graph.node[1])
    assert im2col_node.get_nodeattr("depthwise") == 1
示例#14
0
def test_code_gen_trafo():
    idt = wdt = odt = DataType.BIPOLAR
    mw = 8
    mh = 8
    pe = 4
    simd = 4

    inp = helper.make_tensor_value_info("inp", TensorProto.FLOAT, [1, mw])
    outp = helper.make_tensor_value_info("outp", TensorProto.FLOAT, [1, mh])
    node_inp_list = ["inp", "weights", "thresh"]
    FCLayer_node = helper.make_node(
        "StreamingFCLayer_Batch",
        node_inp_list,
        ["outp"],
        domain="finn",
        backend="fpgadataflow",
        code_gen_dir="",
        executable_path="",
        resType="ap_resource_lut()",
        MW=mw,
        MH=mh,
        SIMD=simd,
        PE=pe,
        inputDataType=idt.name,
        weightDataType=wdt.name,
        outputDataType=odt.name,
        noActivation=1,
    )
    graph = helper.make_graph(nodes=[FCLayer_node],
                              name="fclayer_graph",
                              inputs=[inp],
                              outputs=[outp])

    model = helper.make_model(graph, producer_name="fclayer-model")
    model = ModelWrapper(model)

    model.set_tensor_datatype("inp", idt)
    model.set_tensor_datatype("outp", odt)
    model.set_tensor_datatype("weights", wdt)
    W = util.gen_finn_dt_tensor(wdt, (mw, mh))
    model.set_initializer("weights", W)

    model = model.transform(CodeGen_npysim())
    for node in model.graph.node:
        code_gen_attribute = util.get_by_name(node.attribute,
                                              "code_gen_dir_npysim")
        tmp_dir = code_gen_attribute.s.decode("UTF-8")
        assert os.path.isdir(
            tmp_dir), """Code generation directory of node with
            op type {} does not exist!""".format(node.op_type)
        assert (len(os.listdir(tmp_dir)) !=
                0), """Code generation directory of node with
            op type {} is empty!""".format(node.op_type)
示例#15
0
def test_sort_nonlinear_graph():
    ch = 2
    ifmdim = 16
    input_shape = (1, ch, ifmdim, ifmdim)

    top_in = helper.make_tensor_value_info("top_in", TensorProto.FLOAT,
                                           input_shape)
    top_out = helper.make_tensor_value_info("top_out", TensorProto.FLOAT,
                                            input_shape)

    num_of_params = 8
    value_info = []
    for i in range(num_of_params):
        value_info += [
            helper.make_tensor_value_info("p" + str(i), TensorProto.FLOAT,
                                          input_shape)
        ]

    modelproto = helper.make_model(
        helper.make_graph(
            name="test",
            inputs=[top_in],
            outputs=[top_out],
            value_info=value_info,
            nodes=[
                # Not sorted nodes
                helper.make_node("Mul", ["fork1", "p2"], ["t3"]),
                helper.make_node("Add", ["t4", "p3"], ["t5"]),
                helper.make_node("Add", ["t2", "t3"], ["t4"]),
                helper.make_node("Add", ["t6", "t7"], ["t8"]),
                helper.make_node("Add", ["fork3", "fork3"], ["top_out"]),
                helper.make_node("Mul", ["t5", "p4"], ["fork2"]),
                helper.make_node("Add", ["top_in", "p0"], ["fork1"]),
                helper.make_node("Mul", ["fork1", "p1"], ["t2"]),
                helper.make_node("Add", ["fork2", "p5"], ["t6"]),
                helper.make_node("Add", ["fork2", "p6"], ["t7"]),
                helper.make_node("Mul", ["t8", "p7"], ["fork3"]),
            ],
        ))
    model = ModelWrapper(modelproto)
    model = model.transform(InferShapes())

    np.random.seed(0)
    for i in range(num_of_params):
        model.set_initializer("p" + str(i),
                              np.random.rand(*input_shape).astype(np.float32))

    new_model = model.transform(SortGraph())

    # Test
    ret = new_model.analysis(ta.nodes_topologically_sorted)
    assert ret[
        "nodes_topologically_sorted"], "Nodes are not topologically sorted."
示例#16
0
def test_compilation_trafo():
    idt = wdt = odt = DataType.BIPOLAR
    mw = 8
    mh = 8
    pe = 4
    simd = 4

    inp = helper.make_tensor_value_info("inp", TensorProto.FLOAT, [1, mw])
    outp = helper.make_tensor_value_info("outp", TensorProto.FLOAT, [1, mh])
    node_inp_list = ["inp", "weights", "thresh"]
    FCLayer_node = helper.make_node(
        "StreamingFCLayer_Batch",
        node_inp_list,
        ["outp"],
        domain="finn.custom_op.fpgadataflow",
        backend="fpgadataflow",
        code_gen_dir="",
        executable_path="",
        MW=mw,
        MH=mh,
        SIMD=simd,
        PE=pe,
        inputDataType=idt.name,
        weightDataType=wdt.name,
        outputDataType=odt.name,
        noActivation=1,
    )
    graph = helper.make_graph(nodes=[FCLayer_node],
                              name="fclayer_graph",
                              inputs=[inp],
                              outputs=[outp])

    model = helper.make_model(graph, producer_name="fclayer-model")
    model = ModelWrapper(model)

    model.set_tensor_datatype("inp", idt)
    model.set_tensor_datatype("outp", odt)
    model.set_tensor_datatype("weights", wdt)
    W = util.gen_finn_dt_tensor(wdt, (mw, mh))
    model.set_initializer("weights", W)

    model = model.transform(PrepareCppSim())
    model = model.transform(CompileCppSim())
    for node in model.graph.node:
        compilation_attribute = util.get_by_name(node.attribute,
                                                 "executable_path")
        executable = compilation_attribute.s.decode("UTF-8")
        print(executable)
        assert os.path.isfile(executable), """Executable of node with
            op type {} does not exist!""".format(node.op_type)
示例#17
0
def test_collapse_repeated_op():
    top_in = oh.make_tensor_value_info("top_in", TensorProto.FLOAT, [2])
    add_param_0 = oh.make_tensor_value_info("add_param_0", TensorProto.FLOAT, [2])
    mul_param_0 = oh.make_tensor_value_info("mul_param_0", TensorProto.FLOAT, [2])
    add_param_1 = oh.make_tensor_value_info("add_param_1", TensorProto.FLOAT, [2])
    mul_param_1 = oh.make_tensor_value_info("mul_param_1", TensorProto.FLOAT, [2])
    top_out = oh.make_tensor_value_info("top_out", TensorProto.FLOAT, [2])
    modelproto = oh.make_model(
        oh.make_graph(
            name="test",
            inputs=[top_in],
            outputs=[top_out],
            value_info=[add_param_0, mul_param_0, add_param_1, mul_param_1],
            nodes=[
                oh.make_node("Add", ["top_in", "add_param_0"], ["middle_0"]),
                oh.make_node("Add", ["middle_0", "add_param_1"], ["middle_1"]),
                oh.make_node("Mul", ["middle_1", "mul_param_0"], ["middle_2"]),
                oh.make_node("Mul", ["middle_2", "mul_param_1"], ["top_out"]),
            ],
        )
    )
    model = ModelWrapper(modelproto)
    model = model.transform(InferShapes())
    model.set_initializer("add_param_0", np.asarray([1, 3], dtype=np.float32))
    model.set_initializer("add_param_1", np.asarray([-1, 3], dtype=np.float32))
    model.set_initializer("mul_param_0", np.asarray([2, 4], dtype=np.float32))
    model.set_initializer("mul_param_1", np.asarray([2, -4], dtype=np.float32))
    new_model = model.transform(CollapseRepeatedAdd())
    new_model = new_model.transform(CollapseRepeatedMul())
    inp_dict = {"top_in": np.asarray([-1.0, 1.0], dtype=np.float32)}
    assert ox.compare_execution(model, new_model, inp_dict)
    assert len(new_model.graph.node) == 2
    assert new_model.graph.node[0].op_type == "Add"
    assert new_model.graph.node[1].op_type == "Mul"
示例#18
0
def make_model(shape):
    inp1 = helper.make_tensor_value_info("inp1", TensorProto.FLOAT, shape)
    inp2 = helper.make_tensor_value_info("inp2", TensorProto.FLOAT, shape)
    inp1_add = helper.make_tensor_value_info("inp1_add", TensorProto.FLOAT,
                                             shape)
    inp1_add_ct = helper.make_tensor_value_info("inp1_add_ct",
                                                TensorProto.FLOAT, [1])
    inp2_add = helper.make_tensor_value_info("inp2_add", TensorProto.FLOAT,
                                             shape)
    inp2_add_ct = helper.make_tensor_value_info("inp2_add_ct",
                                                TensorProto.FLOAT, [1])
    inp1_mul = helper.make_tensor_value_info("inp1_mul", TensorProto.FLOAT,
                                             shape)
    inp1_mul_ct = helper.make_tensor_value_info("inp1_mul_ct",
                                                TensorProto.FLOAT, [1])
    inp2_mul = helper.make_tensor_value_info("inp2_mul", TensorProto.FLOAT,
                                             shape)
    inp2_mul_ct = helper.make_tensor_value_info("inp2_mul_ct",
                                                TensorProto.FLOAT, [1])
    outp = helper.make_tensor_value_info("outp", TensorProto.FLOAT, shape)

    add1_node = helper.make_node("Add", [inp1.name, inp1_add_ct.name],
                                 [inp1_add.name])
    add2_node = helper.make_node("Add", [inp2.name, inp2_add_ct.name],
                                 [inp2_add.name])
    mul1_node = helper.make_node("Mul", [inp1_add.name, inp1_mul_ct.name],
                                 [inp1_mul.name])
    mul2_node = helper.make_node("Mul", [inp2_add.name, inp2_mul_ct.name],
                                 [inp2_mul.name])
    eltwise_add_node = helper.make_node("Add", [inp1_mul.name, inp2_mul.name],
                                        [outp.name])
    graph = helper.make_graph(
        nodes=[add1_node, add2_node, mul1_node, mul2_node, eltwise_add_node],
        name="graph",
        inputs=[inp1, inp2],
        outputs=[outp],
    )

    model = helper.make_model(graph, producer_name="add-model")
    model = ModelWrapper(model)

    # set initializers for scalar add/mul nodes
    model.set_initializer(add1_node.input[1], np.array([7.0]))
    model.set_initializer(add2_node.input[1], np.array([8.0]))
    model.set_initializer(mul1_node.input[1], np.array([3.0]))
    model.set_initializer(mul2_node.input[1], np.array([3.0]))

    return model
示例#19
0
def test_move_add_past_mul_only_if_linear():
    top_in = oh.make_tensor_value_info("top_in", TensorProto.FLOAT, [2])
    top_out = oh.make_tensor_value_info("top_out", TensorProto.FLOAT, [2])

    value_info = [
        oh.make_tensor_value_info("add1_param", TensorProto.FLOAT, [1])
    ]
    value_info += [
        oh.make_tensor_value_info("mul1_param", TensorProto.FLOAT, [1])
    ]
    value_info += [
        oh.make_tensor_value_info("mul2_param", TensorProto.FLOAT, [1])
    ]
    value_info += [
        oh.make_tensor_value_info("mul3_param", TensorProto.FLOAT, [1])
    ]
    modelproto = oh.make_model(
        oh.make_graph(
            name="test",
            inputs=[top_in],
            outputs=[top_out],
            value_info=value_info,
            nodes=[
                oh.make_node("Add", ["top_in", "add1_param"], ["t1"]),
                oh.make_node("Mul", ["t1", "mul1_param"], ["fork"]),
                oh.make_node("Mul", ["fork", "mul2_param"], ["t3"]),
                oh.make_node("Add", ["t3", "fork"], ["t4"]),
                oh.make_node("Mul", ["t4", "mul3_param"], ["top_out"]),
            ],
        ))
    model = ModelWrapper(modelproto)
    model = model.transform(InferShapes())

    np.random.seed(0)
    model.set_initializer("add1_param", np.random.rand(2).astype(np.float32))
    model.set_initializer("mul1_param", np.random.rand(2).astype(np.float32))
    model.set_initializer("mul2_param", np.random.rand(2).astype(np.float32))
    model.set_initializer("mul3_param", np.random.rand(2).astype(np.float32))
    new_model = model.transform(MoveAddPastMul())
    inp_dict = {"top_in": np.random.rand(2).astype(np.float32)}
    assert ox.compare_execution(model, new_model, inp_dict)
    assert new_model.graph.node[0].op_type == "Mul"
    assert new_model.graph.node[1].op_type == "Add"
    assert new_model.graph.node[2].op_type == "Mul"
    assert new_model.graph.node[3].op_type == "Add"
    assert new_model.graph.node[4].op_type == "Mul"
示例#20
0
def test_absorb_opposite_transposes():
    np.random.seed(0)
    input_shape = [1, 3, 4, 2]
    top_in = oh.make_tensor_value_info("top_in", TensorProto.FLOAT,
                                       input_shape)
    top_out = oh.make_tensor_value_info("top_out", TensorProto.FLOAT,
                                        input_shape)
    value_info = [
        oh.make_tensor_value_info("add_param_0", TensorProto.FLOAT, [1])
    ]
    value_info += [
        oh.make_tensor_value_info("add_param_1", TensorProto.FLOAT, [1])
    ]
    value_info += [
        oh.make_tensor_value_info("mul_param_0", TensorProto.FLOAT, [1])
    ]
    modelproto = oh.make_model(
        oh.make_graph(
            name="test",
            inputs=[top_in],
            outputs=[top_out],
            value_info=value_info,
            nodes=[
                oh.make_node("Add", ["top_in", "add_param_0"], ["t0"]),
                oh.make_node("Transpose", ["t0"], ["t1"], perm=[0, 2, 3, 1]),
                oh.make_node("Transpose", ["t1"], ["t2"], perm=[0, 3, 1, 2]),
                oh.make_node("Add", ["t2", "add_param_1"], ["t3"]),
                oh.make_node("Transpose", ["t3"], ["t4"], perm=[0, 2, 3, 1]),
                oh.make_node("Transpose", ["t4"], ["t5"], perm=[0, 3, 1, 2]),
                oh.make_node("Add", ["t5", "t2"], ["t6"]),
                oh.make_node("Mul", ["t6", "mul_param_0"], ["top_out"]),
            ],
        ))
    model = ModelWrapper(modelproto)
    model = model.transform(InferShapes())
    model.set_initializer("add_param_0", np.asarray([1], dtype=np.float32))
    model.set_initializer("add_param_1", np.asarray([3], dtype=np.float32))
    model.set_initializer("mul_param_0", np.asarray([2], dtype=np.float32))
    new_model = model.transform(AbsorbConsecutiveTransposes())
    new_model = new_model.transform(InferShapes())
    inp_dict = {"top_in": np.random.rand(*input_shape).astype(np.float32)}
    assert ox.compare_execution(model, model, inp_dict)
    assert len(new_model.graph.node) == 4
    for n in new_model.graph.node:
        assert new_model.graph.node[0].op_type != "Transpose"
示例#21
0
def make_randomly_sorted_linear_model(num_of_nodes, seed=None):
    if seed is not None:
        np.random.seed(seed)

    ch = 2
    ifmdim = 16
    input_shape = (1, ch, ifmdim, ifmdim)

    top_in = helper.make_tensor_value_info("t0", TensorProto.FLOAT, input_shape)
    top_out = helper.make_tensor_value_info(
        "t" + str(num_of_nodes), TensorProto.FLOAT, input_shape
    )

    value_info = []
    nodes = []
    for i in range(num_of_nodes):
        nodes += [
            helper.make_node("Add", ["t" + str(i), "p" + str(i)], ["t" + str(i + 1)])
        ]
        value_info += [
            helper.make_tensor_value_info("p" + str(i), TensorProto.FLOAT, input_shape)
        ]

    nodes = np.random.permutation(nodes)

    modelproto = helper.make_model(
        helper.make_graph(
            name="test",
            inputs=[top_in],
            outputs=[top_out],
            value_info=value_info,
            nodes=nodes,
        )
    )
    model = ModelWrapper(modelproto)
    model = model.transform(InferShapes())

    for i in range(num_of_nodes):
        model.set_initializer(
            "p" + str(i), np.random.rand(*input_shape).astype(np.float32)
        )

    return model
示例#22
0
def test_factor_out_mul_sign_magnitude():
    top_in = oh.make_tensor_value_info("top_in", TensorProto.FLOAT, [1, 2])
    mul_param = oh.make_tensor_value_info("mul_param", TensorProto.FLOAT,
                                          [1, 2])
    top_out = oh.make_tensor_value_info("top_out", TensorProto.FLOAT, [1, 2])
    modelproto = oh.make_model(
        oh.make_graph(
            name="test",
            inputs=[top_in],
            outputs=[top_out],
            value_info=[mul_param],
            nodes=[oh.make_node("Mul", ["top_in", "mul_param"], ["top_out"])],
        ))
    model = ModelWrapper(modelproto)
    model = model.transform(InferShapes())
    model.set_initializer("mul_param", np.asarray([[-1, 4]], dtype=np.float32))
    new_model = model.transform(FactorOutMulSignMagnitude())
    inp_dict = {"top_in": np.asarray([[-1.0, 1.0]], dtype=np.float32)}
    assert ox.compare_execution(model, new_model, inp_dict)
示例#23
0
def make_single_thresholding_modelwrapper(T, pe, idt, odt, actval, mem_mode):
    NumChannels = T.shape[0]

    inp = helper.make_tensor_value_info("inp", TensorProto.FLOAT,
                                        [1, NumChannels])
    outp = helper.make_tensor_value_info("outp", TensorProto.FLOAT,
                                         [1, NumChannels])

    node_inp_list = ["inp", "thresh"]

    Thresholding_node = helper.make_node(
        "Thresholding_Batch",
        node_inp_list,
        ["outp"],
        domain="finn.custom_op.fpgadataflow",
        backend="fpgadataflow",
        NumChannels=NumChannels,
        PE=pe,
        numSteps=T.shape[1],
        inputDataType=idt.name,
        weightDataType=idt.name,  # will be set by MinimizeAccumulatorWidth
        outputDataType=odt.name,
        ActVal=actval,
        mem_mode=mem_mode,
    )
    graph = helper.make_graph(
        nodes=[Thresholding_node],
        name="thresholding_graph",
        inputs=[inp],
        outputs=[outp],
    )

    model = helper.make_model(graph, producer_name="thresholding-model")
    model = ModelWrapper(model)

    model.set_tensor_datatype("inp", idt)
    model.set_tensor_datatype("outp", odt)

    model.set_tensor_datatype("thresh", idt)
    model.set_initializer("thresh", T)
    return model
示例#24
0
def test_move_scalar_past_matmul_only_if_linear(test_args):
    scalar_op = test_args[0]
    transf_fxn = test_args[1]
    input_shape = [1, 2]
    matmul_shape = [2, 2]
    top_in = oh.make_tensor_value_info("top_in", TensorProto.FLOAT,
                                       input_shape)
    top_out = oh.make_tensor_value_info("top_out", TensorProto.FLOAT,
                                        input_shape)

    p1 = oh.make_tensor_value_info("p1", TensorProto.FLOAT, [1, 1])
    p2 = oh.make_tensor_value_info("p2", TensorProto.FLOAT, matmul_shape)
    p3 = oh.make_tensor_value_info("p3", TensorProto.FLOAT, matmul_shape)
    p4 = oh.make_tensor_value_info("p4", TensorProto.FLOAT, matmul_shape)
    modelproto = oh.make_model(
        oh.make_graph(
            name="test",
            inputs=[top_in],
            outputs=[top_out],
            value_info=[p1, p2, p3, p4],
            nodes=[
                oh.make_node(scalar_op, ["top_in", "p1"], ["t1"]),
                oh.make_node("MatMul", ["t1", "p2"], ["fork"]),
                oh.make_node("MatMul", ["fork", "p3"], ["t3"]),
                oh.make_node(scalar_op, ["t3", "fork"], ["t4"]),
                oh.make_node("MatMul", ["t4", "p4"], ["top_out"]),
            ],
        ))
    model = ModelWrapper(modelproto)
    model = model.transform(InferShapes())

    np.random.seed(0)
    model.set_initializer("p1", np.random.rand(1, 1).astype(np.float32))
    model.set_initializer("p2",
                          np.random.rand(*matmul_shape).astype(np.float32))
    model.set_initializer("p3",
                          np.random.rand(*matmul_shape).astype(np.float32))
    model.set_initializer("p4",
                          np.random.rand(*matmul_shape).astype(np.float32))

    # Transform
    new_model = model.transform(transf_fxn)

    # Test
    inp_dict = {"top_in": np.random.rand(*input_shape).astype(np.float32)}
    assert ox.compare_execution(model, new_model, inp_dict)
    assert new_model.graph.node[0].op_type == "MatMul"
    assert new_model.graph.node[1].op_type == scalar_op
    assert new_model.graph.node[2].op_type == "MatMul"
    assert new_model.graph.node[3].op_type == scalar_op
    assert new_model.graph.node[4].op_type == "MatMul"
示例#25
0
def test_modelwrapper():
    lfc = get_test_model_trained("LFC", 1, 1)
    bo.export_finn_onnx(lfc, (1, 1, 28, 28), export_onnx_path)
    model = ModelWrapper(export_onnx_path)
    assert model.check_all_tensor_shapes_specified() is False
    inp_shape = model.get_tensor_shape("0")
    assert inp_shape == [1, 1, 28, 28]
    l0_mat_tensor_name = "33"
    l0_weights = model.get_initializer(l0_mat_tensor_name)
    assert l0_weights.shape == (784, 1024)
    l0_weights_hist = Counter(l0_weights.flatten())
    assert l0_weights_hist[1.0] == 401311 and l0_weights_hist[-1.0] == 401505
    l0_weights_rand = np.random.randn(784, 1024)
    model.set_initializer(l0_mat_tensor_name, l0_weights_rand)
    assert (model.get_initializer(l0_mat_tensor_name) == l0_weights_rand).all()
    l0_inp_tensor_name = "32"
    inp_cons = model.find_consumer(l0_inp_tensor_name)
    assert inp_cons.op_type == "MatMul"
    out_prod = model.find_producer(l0_inp_tensor_name)
    assert out_prod.op_type == "Sign"
    os.remove(export_onnx_path)
示例#26
0
def make_single_maxpool_modelwrapper(onnx_op_name, ishape, idt, pdt, pshape):

    inp = helper.make_tensor_value_info("inp", TensorProto.FLOAT, ishape)
    outp = helper.make_tensor_value_info("outp", TensorProto.FLOAT, ishape)
    p0 = helper.make_tensor_value_info("p0", TensorProto.FLOAT, pshape)

    model = helper.make_model(
        helper.make_graph(
            name="test",
            inputs=[inp],
            outputs=[outp],
            value_info=[p0],
            nodes=[helper.make_node(onnx_op_name, ["inp", "p0"], ["outp"])],
        ))

    model = ModelWrapper(model)
    model.set_initializer("p0", gen_finn_dt_tensor(pdt, pshape))
    model.set_tensor_datatype("inp", idt)
    model.transform(InferDataLayouts(), make_deepcopy=False)
    model.transform(InferShapes(), make_deepcopy=False)
    return model
def test_move_flatten_past_affine(data_layout, batch_size):
    if data_layout == DataLayout.NHWC:
        ishape = [batch_size, 1, 1, 1024]
        oshape = [batch_size, 1000]
    else:
        ishape = [batch_size, 1024, 1, 1]
        oshape = [batch_size, 1000]

    inp = helper.make_tensor_value_info("inp", TensorProto.FLOAT, ishape)
    a0 = helper.make_tensor_value_info("a1", TensorProto.FLOAT, [1024, 1000])
    a1 = helper.make_tensor_value_info("a2", TensorProto.FLOAT, [])
    a2 = helper.make_tensor_value_info("a3", TensorProto.FLOAT, [1000])
    outp = helper.make_tensor_value_info("outp", TensorProto.FLOAT, oshape)

    flatten_node = helper.make_node("Flatten", ["inp"], ["flatten_out"])
    matmul_node = helper.make_node("MatMul", ["flatten_out", "a0"], ["matmul_out"])
    mul_node = helper.make_node("Mul", ["matmul_out", "a1"], ["mul_out"])
    add_node = helper.make_node("Add", ["mul_out", "a2"], ["outp"])

    graph = helper.make_graph(
        nodes=[flatten_node, matmul_node, mul_node, add_node],
        name="move-reshape-graph",
        inputs=[inp],
        outputs=[outp],
        value_info=[a0, a1, a2],
    )

    model = helper.make_model(graph, producer_name="move_reshape_model")
    model = ModelWrapper(model)

    # initialize values
    a0_values = gen_finn_dt_tensor(DataType["TERNARY"], [1024, 1000])
    model.set_initializer("a0", a0_values)
    a1_values = np.random.uniform(low=0.1, high=0.99, size=(1)).astype(np.float32)
    model.set_initializer("a1", a1_values)
    a2_values = np.random.uniform(low=-1, high=1, size=(1000)).astype(np.float32)
    model.set_initializer("a2", a2_values)

    model.set_tensor_datatype("inp", DataType["INT2"])
    model.set_tensor_layout("inp", data_layout)
    model = model.transform(InferShapes())
    model = model.transform(InferDataTypes())
    model = model.transform(InferDataLayouts())
    model = model.transform(GiveUniqueNodeNames())
    model = model.transform(GiveReadableTensorNames())

    # compare execution before and after transformation
    inp_values = gen_finn_dt_tensor(DataType["INT2"], ishape)
    idict = {model.graph.input[0].name: inp_values}
    model_transformed = model.transform(MoveFlattenPastAffine())
    assert oxe.compare_execution(model, model_transformed, idict)

    # depending on data layout check if graph is transformed or not
    if data_layout == DataLayout.NHWC:
        # check if nodes have new order in transformed graph
        assert model.graph != model_transformed.graph
        assert model_transformed.graph.node[-1].op_type == "Flatten"
    else:
        assert model.graph == model_transformed.graph
def test_remove_identity_ops(op, as_first_node, approx):

    # set up onnx model
    inp = helper.make_tensor_value_info("inp", TensorProto.FLOAT, [1, 4, 1, 1])
    mul = helper.make_tensor_value_info("mul", TensorProto.FLOAT, [])
    shape = helper.make_tensor_value_info("shape", TensorProto.FLOAT, [2])
    div = helper.make_tensor_value_info("div", TensorProto.FLOAT, [])
    matmul = helper.make_tensor_value_info("matmul", TensorProto.FLOAT, [4, 2])
    outp = helper.make_tensor_value_info("outp", TensorProto.FLOAT, [1, 2])

    mul_node = helper.make_node("Mul", ["inp", "mul"], ["mul_out"])
    reshape_node = helper.make_node("Reshape", ["mul_out", "shape"], ["reshape_out"])
    div_node = helper.make_node("Div", ["reshape_out", "div"], ["div_out"])
    matmul_node = helper.make_node("MatMul", ["div_out", "matmul"], ["outp"])

    graph = helper.make_graph(
        nodes=[mul_node, reshape_node, div_node, matmul_node],
        name="identity-graph",
        inputs=[inp],
        outputs=[outp],
        value_info=[mul, shape, div, matmul],
    )

    model = helper.make_model(graph, producer_name="mulpastconv-model")
    model = ModelWrapper(model)
    inp_values = gen_finn_dt_tensor(DataType["INT2"], [1, 4, 1, 1])
    mul_values = np.random.uniform(low=0.1, high=0.99, size=(1)).astype(np.float32)
    shape_values = np.asarray([1, -1], dtype=np.int64)
    div_values = np.random.uniform(low=0.1, high=0.99, size=(1)).astype(np.float32)
    matmul_values = gen_finn_dt_tensor(DataType["INT2"], [4, 2])
    model.set_initializer("mul", mul_values)
    model.set_initializer("shape", shape_values)
    model.set_initializer("div", div_values)
    model.set_initializer("matmul", matmul_values)
    insert_identity_op(model, op, as_first_node, approx)
    model = model.transform(InferShapes())
    model = model.transform(InferDataTypes())
    idict = {"inp": inp_values}
    odict = oxe.execute_onnx(model, idict)
    out_before = odict["outp"]
    num_of_nodes_before = len(model.graph.node)

    model = model.transform(RemoveIdentityOps())
    num_of_nodes_after = len(model.graph.node)
    assert num_of_nodes_before - 1 == num_of_nodes_after

    odict = oxe.execute_onnx(model, idict)
    out_after = odict["outp"]
    assert np.isclose(out_before, out_after, atol=1e-3).all()
示例#29
0
def test_modelwrapper():
    raw_m = get_data("finn.data", "onnx/mnist-conv/model.onnx")
    model = ModelWrapper(raw_m)
    assert model.check_all_tensor_shapes_specified() is True
    inp_name = model.graph.input[0].name
    inp_shape = model.get_tensor_shape(inp_name)
    assert inp_shape == [1, 1, 28, 28]
    conv_nodes = model.get_nodes_by_op_type("Conv")
    matmul_nodes = model.get_nodes_by_op_type("MatMul")
    assert len(conv_nodes) == 2
    assert len(matmul_nodes) == 1
    first_conv = conv_nodes[0]
    first_conv_iname = first_conv.input[0]
    first_conv_wname = first_conv.input[1]
    first_conv_oname = first_conv.output[0]
    assert first_conv_iname != "" and (first_conv_iname is not None)
    assert first_conv_wname != "" and (first_conv_wname is not None)
    assert first_conv_oname != "" and (first_conv_oname is not None)
    first_conv_weights = model.get_initializer(first_conv_wname)
    assert first_conv_weights.shape == (8, 1, 5, 5)
    first_conv_weights_rand = np.random.randn(8, 1, 5, 5)
    model.set_initializer(first_conv_wname, first_conv_weights_rand)
    assert (model.get_initializer(first_conv_wname) == first_conv_weights_rand
            ).all()
    inp_cons = model.find_consumer(first_conv_iname)
    assert inp_cons == first_conv
    out_prod = model.find_producer(first_conv_oname)
    assert out_prod == first_conv
    inp_layout = model.get_tensor_layout(first_conv_iname)
    assert inp_layout is None
    inp_layout = DataLayout.NCHW
    model.set_tensor_layout(first_conv_iname, inp_layout)
    assert model.get_tensor_layout(first_conv_iname) == inp_layout
    inp_sparsity = model.get_tensor_sparsity(first_conv_iname)
    assert inp_sparsity is None
    inp_sparsity = {"dw": {"kernel_shape": [3, 3]}}
    model.set_tensor_sparsity(first_conv_iname, inp_sparsity)
    assert model.get_tensor_sparsity(first_conv_iname) == inp_sparsity
def test_batchnorm_to_affine_epsilon(epsilon):
    """Dummy batchnorm node to test out the epsilon attribute."""

    batchnorm_node = onnx.helper.make_node(
        "BatchNormalization",
        inputs=["x", "s", "bias", "mean", "var"],
        outputs=["y"],
        epsilon=epsilon,
    )

    x = onnx.helper.make_tensor_value_info("x", onnx.TensorProto.FLOAT,
                                           [1, 3, 5, 5])
    s = onnx.helper.make_tensor_value_info("s", onnx.TensorProto.FLOAT, [3])
    bias = onnx.helper.make_tensor_value_info("bias", onnx.TensorProto.FLOAT,
                                              [3])
    mean = onnx.helper.make_tensor_value_info("mean", onnx.TensorProto.FLOAT,
                                              [3])
    var = onnx.helper.make_tensor_value_info("var", onnx.TensorProto.FLOAT,
                                             [3])
    y = onnx.helper.make_tensor_value_info("y", onnx.TensorProto.FLOAT,
                                           [1, 3, 5, 5])

    # Graph
    graph = onnx.helper.make_graph(
        nodes=[batchnorm_node],
        name="test_batchnorm_graph",
        inputs=[x],
        outputs=[y],
        value_info=[s, bias, mean, var],
    )

    onnx_model = onnx.helper.make_model(graph,
                                        producer_name="test_batchnorm-model")
    model = ModelWrapper(onnx_model)

    model.set_initializer("s", np.array([1, 2, 3]).astype(np.float32))
    model.set_initializer("bias", np.array([1, 2, 3]).astype(np.float32))
    model.set_initializer("mean", np.array([3, 4, 5]).astype(np.float32))
    model.set_initializer("var", np.array([0.5, 0.7, 0.3]).astype(np.float32))

    i_val = np.arange(0, 3 * 5 * 5, dtype=np.float32)
    i_val = np.reshape(i_val, [1, 3, 5, 5])
    input_dict = {"x": i_val}
    output_node_name = "y"

    output_dict = oxe.execute_onnx(model,
                                   input_dict,
                                   return_full_exec_context=True)
    output_original = output_dict[output_node_name]

    model_lowered = model.transform(BatchNormToAffine())
    output_dict = oxe.execute_onnx(model_lowered,
                                   input_dict,
                                   return_full_exec_context=True)
    output_lowered = output_dict[output_node_name]

    assert (output_original == output_lowered).all()