def make_single_maxpool_modelwrapper(k, stride, pad, ifm_ch, ifm_dim, ofm_dim,
                                     idt):
    odt = idt
    inp = helper.make_tensor_value_info("inp", TensorProto.FLOAT,
                                        [1, ifm_ch, ifm_dim, ifm_dim])
    outp = helper.make_tensor_value_info("outp", TensorProto.FLOAT,
                                         [1, ifm_ch, ofm_dim, ofm_dim])

    mp_node = helper.make_node(
        "MaxPool",
        ["inp"],
        ["outp"],
        kernel_shape=[k, k],
        pads=[pad, pad, pad, pad],
        strides=[stride, stride],
    )
    graph = helper.make_graph(nodes=[mp_node],
                              name="mp_graph",
                              inputs=[inp],
                              outputs=[outp])

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

    model.set_tensor_datatype("inp", idt)
    model.set_tensor_datatype("outp", odt)
    model = model.transform(InferShapes())

    return model
def make_single_im2col_modelwrapper(
    k, ifm_ch, ifm_dim, ofm_dim, simd, stride, dilation, idt
):
    odt = idt
    inp = helper.make_tensor_value_info(
        "inp", TensorProto.FLOAT, [1, ifm_dim, ifm_dim, ifm_ch]
    )
    outp = helper.make_tensor_value_info(
        "outp", TensorProto.FLOAT, [1, ofm_dim, ofm_dim, k * k * ifm_ch]
    )

    im2col_node = helper.make_node(
        "Im2Col",
        ["inp"],
        ["outp"],
        domain="finn.custom_op.general",
        stride=[stride, stride],
        kernel_size=[k, k],
        input_shape=str((1, ifm_dim, ifm_dim, ifm_ch)),
        pad_amount=[0, 0, 0, 0],
        pad_value=0,
        dilations=[dilation, dilation],
    )
    graph = helper.make_graph(
        nodes=[im2col_node], name="im2col_graph", inputs=[inp], outputs=[outp]
    )

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

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

    return model
Esempio n. 3
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
Esempio n. 4
0
def make_single_fifo_modelwrapper(Shape, Depth, fld_shape, finn_dtype):

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

    FIFO_node = helper.make_node(
        "StreamingFIFO",
        ["inp"],
        ["outp"],
        domain="finn",
        backend="fpgadataflow",
        depth=Depth,
        folded_shape=fld_shape,
        dataType=str(finn_dtype.name),
    )

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

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

    model.set_tensor_datatype("inp", finn_dtype)
    model.set_tensor_datatype("outp", finn_dtype)

    return model
def make_single_quantavpool_modelwrapper(k, stride, ifm_ch, ifm_dim, ofm_dim,
                                         idt, odt):
    inp = helper.make_tensor_value_info("inp", TensorProto.FLOAT,
                                        [1, ifm_ch, ifm_dim, ifm_dim])
    outp = helper.make_tensor_value_info("outp", TensorProto.FLOAT,
                                         [1, ifm_ch, ofm_dim, ofm_dim])

    mp_node = helper.make_node(
        "QuantAvgPool2d",
        ["inp"],
        ["outp"],
        domain="finn.custom_op.general",
        stride=stride,
        kernel=k,
        ibits=idt.bitwidth(),
        obits=odt.bitwidth(),
        signed=1 if idt.signed() else 0,
        data_layout="NCHW",
    )
    graph = helper.make_graph(nodes=[mp_node],
                              name="mp_graph",
                              inputs=[inp],
                              outputs=[outp])

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

    model.set_tensor_datatype("inp", idt)
    model.set_tensor_datatype("outp", odt)
    model = model.transform(InferShapes())

    return model
Esempio n. 6
0
def make_single_im2col_modelwrapper(k, ifm_ch, ifm_dim, ofm_dim, simd, stride,
                                    idt):
    odt = idt
    inp = helper.make_tensor_value_info("inp", TensorProto.FLOAT,
                                        [1, ifm_dim, ifm_dim, ifm_ch])
    outp = helper.make_tensor_value_info("outp", TensorProto.FLOAT,
                                         [1, ofm_dim, ofm_dim, k * k * ifm_ch])

    im2col_node = helper.make_node(
        "Im2Col",
        ["inp"],
        ["outp"],
        domain="finn",
        backend="fpgadataflow",
        stride=stride,
        kernel_size=k,
        input_shape=str((1, ifm_dim, ifm_dim, ifm_ch)),
        pad_amount=0,
        pad_value=0,
    )
    graph = helper.make_graph(nodes=[im2col_node],
                              name="im2col_graph",
                              inputs=[inp],
                              outputs=[outp])

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

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

    return model
Esempio n. 7
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()
Esempio n. 8
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()
def make_single_streamingmaxpool_modelwrapper(k, ifm_ch, ifm_dim, ofm_dim,
                                              idt):
    odt = idt
    inp = helper.make_tensor_value_info("inp", TensorProto.FLOAT,
                                        [1, ifm_dim, ifm_dim, ifm_ch])
    outp = helper.make_tensor_value_info("outp", TensorProto.FLOAT,
                                         [1, ofm_dim, ofm_dim, ifm_ch])

    smp_node = helper.make_node(
        "StreamingMaxPool_Batch",
        ["inp"],
        ["outp"],
        domain="finn",
        backend="fpgadataflow",
        PoolDim=k,
        NumChannels=ifm_ch,
        ImgDim=ifm_dim,
        dataType=idt.name,
    )
    graph = helper.make_graph(nodes=[smp_node],
                              name="smp_graph",
                              inputs=[inp],
                              outputs=[outp])

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

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

    return model
def make_labelselect_modelwrapper(labels, pe, k, idt):
    inp = helper.make_tensor_value_info("inp", TensorProto.FLOAT, [1, labels])
    outp = helper.make_tensor_value_info("outp", TensorProto.FLOAT, [1, k])

    labelselect_node = helper.make_node(
        "LabelSelect_Batch",
        ["inp"],
        ["outp"],
        domain="finn",
        backend="fpgadataflow",
        Labels=labels,
        PE=pe,
        K=k,
        inputDataType=idt.name,
    )
    graph = helper.make_graph(
        nodes=[labelselect_node],
        name="graph",
        inputs=[inp],
        outputs=[outp],
    )

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

    model.set_tensor_datatype("inp", idt)
    odt = DataType.get_smallest_possible(labels - 1)
    model.set_tensor_datatype("outp", odt)

    return model
Esempio n. 11
0
def make_single_dwc_modelwrapper(Shape, INWidth, OUTWidth, finn_dtype):

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

    DWC_node = helper.make_node(
        "StreamingDataWidthConverter_Batch",
        ["inp"],
        ["outp"],
        domain="finn",
        backend="fpgadataflow",
        shape=Shape,
        inWidth=INWidth,
        outWidth=OUTWidth,
        dataType=str(finn_dtype.name),
    )

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

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

    model.set_tensor_datatype("inp", finn_dtype)
    model.set_tensor_datatype("outp", finn_dtype)

    return model
def make_single_maxpoolnhwc_modelwrapper(k, ifm_ch, ifm_dim, ofm_dim, idt):
    odt = idt
    inp = helper.make_tensor_value_info("inp", TensorProto.FLOAT,
                                        [1, ifm_dim, ifm_dim, ifm_ch])
    outp = helper.make_tensor_value_info("outp", TensorProto.FLOAT,
                                         [1, ofm_dim, ofm_dim, ifm_ch])

    mp_node = helper.make_node(
        "MaxPoolNHWC",
        ["inp"],
        ["outp"],
        domain="finn",
        kernel_shape=[k, k],
        strides=[k, k],
        pads=[0, 0, 0, 0],
    )
    graph = helper.make_graph(nodes=[mp_node],
                              name="mp_graph",
                              inputs=[inp],
                              outputs=[outp])

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

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

    return model
Esempio n. 13
0
def make_dupstreams_modelwrapper(ch, pe, idim, idt):
    shape = [1, idim, idim, ch]
    inp = helper.make_tensor_value_info("inp", TensorProto.FLOAT, shape)
    outp0 = helper.make_tensor_value_info("outp0", TensorProto.FLOAT, shape)
    outp1 = helper.make_tensor_value_info("outp1", TensorProto.FLOAT, shape)

    dupstrm_node = helper.make_node(
        "DuplicateStreams_Batch",
        ["inp"],
        ["outp0", "outp1"],
        domain="finn.custom_op.fpgadataflow",
        backend="fpgadataflow",
        NumChannels=ch,
        PE=pe,
        inputDataType=idt.name,
        numInputVectors=[1, idim, idim],
    )
    graph = helper.make_graph(nodes=[dupstrm_node],
                              name="graph",
                              inputs=[inp],
                              outputs=[outp0, outp1])

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

    model.set_tensor_datatype("inp", idt)

    model = model.transform(InferShapes())
    model = model.transform(InferDataTypes())

    return model
Esempio n. 14
0
def test_modelwrapper_setting_unsetting_datatypes():
    # Set and unset some datatypes and check for expected return values
    raw_m = get_data("finn.data", "onnx/mnist-conv/model.onnx")
    model = ModelWrapper(raw_m)

    test_node = model.graph.node[0]
    test_tensor = test_node.output[0]

    ret = model.get_tensor_datatype(test_tensor)
    assert (ret == DataType["FLOAT32"]
            ), "Tensor datatype should be float32 for no initalization."

    model.set_tensor_datatype(test_tensor, None)
    ret = model.get_tensor_datatype(test_tensor)
    assert ret == DataType[
        "FLOAT32"], "An unset datatype should return float32."

    model.set_tensor_datatype(test_tensor, DataType["INT3"])
    ret = model.get_tensor_datatype(test_tensor)
    assert ret == DataType["INT3"], "Tensor datatype should follow setting."

    model.set_tensor_datatype(test_tensor, DataType["UINT4"])
    ret = model.get_tensor_datatype(test_tensor)
    assert ret == DataType["UINT4"], "Tensor datatype should follow setting."

    model.set_tensor_datatype(test_tensor, None)
    ret = model.get_tensor_datatype(test_tensor)
    assert ret == DataType[
        "FLOAT32"], "An unset datatype should return float32."

    model.set_tensor_datatype(test_tensor, DataType["BIPOLAR"])
    ret = model.get_tensor_datatype(test_tensor)
    assert ret == DataType["BIPOLAR"], "Tensor datatype should follow setting."
Esempio n. 15
0
def make_accpool_modelwrapper(ch, pe, idim, idt):
    inp = helper.make_tensor_value_info("inp", TensorProto.FLOAT,
                                        [1, idim, idim, ch])
    outp = helper.make_tensor_value_info("outp", TensorProto.FLOAT,
                                         [1, 1, 1, ch])

    accpool_node = helper.make_node(
        "GlobalAccPool_Batch",
        ["inp"],
        ["outp"],
        domain="finn.custom_op.fpgadataflow",
        backend="fpgadataflow",
        NumChannels=ch,
        PE=pe,
        inputDataType=idt.name,
        numInputVectors=[1, idim, idim],
    )
    graph = helper.make_graph(nodes=[accpool_node],
                              name="graph",
                              inputs=[inp],
                              outputs=[outp])

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

    model.set_tensor_datatype("inp", idt)

    return model
Esempio n. 16
0
def make_addstreams_modelwrapper(ch, pe, idt):
    inp1 = helper.make_tensor_value_info("inp1", TensorProto.FLOAT, [1, ch])
    inp2 = helper.make_tensor_value_info("inp2", TensorProto.FLOAT, [1, ch])
    outp = helper.make_tensor_value_info("outp", TensorProto.FLOAT, [1, ch])

    addstreams_node = helper.make_node(
        "AddStreams_Batch",
        ["inp1", "inp2"],
        ["outp"],
        domain="finn",
        backend="fpgadataflow",
        NumChannels=ch,
        PE=pe,
        inputDataType=idt.name,
    )
    graph = helper.make_graph(
        nodes=[addstreams_node],
        name="graph",
        inputs=[inp1, inp2],
        outputs=[outp],
    )

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

    model.set_tensor_datatype("inp1", idt)
    model.set_tensor_datatype("inp2", idt)

    return model
Esempio n. 17
0
def test_onnx_exec_internal_rounding():
    inp0 = onnx.helper.make_tensor_value_info("inp0", onnx.TensorProto.FLOAT,
                                              [2, 2])
    inp1 = onnx.helper.make_tensor_value_info("inp1", onnx.TensorProto.FLOAT,
                                              [1])
    outp = onnx.helper.make_tensor_value_info("outp", onnx.TensorProto.FLOAT,
                                              [2, 2])
    mul_node = onnx.helper.make_node("Mul",
                                     inputs=["inp0", "inp1"],
                                     outputs=["outp"])
    graph = onnx.helper.make_graph(nodes=[mul_node],
                                   name="mul_graph",
                                   inputs=[inp0, inp1],
                                   outputs=[outp])

    model = onnx.helper.make_model(graph, producer_name="mul-model")
    model = ModelWrapper(model)
    idt = DataType.INT2
    model.set_tensor_datatype("inp0", idt)
    model.set_tensor_datatype("inp1", idt)
    model.transform(InferShapes())

    mul_value = np.asarray([-1], dtype=np.float32)
    inp_int = gen_finn_dt_tensor(idt, [2, 2])
    scale = np.random.uniform(low=0, high=1, size=(2, 2)).astype(np.float32)
    inp_rounded = (inp_int * scale) / (scale + 1e-7)
    input_dict = {"inp0": inp_rounded, "inp1": mul_value}
    output_dict = oxe.execute_onnx(model, input_dict)
    produced = output_dict["outp"]
    expected = np.multiply(inp_int, mul_value)
    assert (produced == expected).all()
Esempio n. 18
0
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
Esempio n. 19
0
def make_single_slidingwindow_modelwrapper(k,
                                           ifm_ch,
                                           ifm_dim,
                                           ofm_dim,
                                           simd,
                                           stride,
                                           dilation,
                                           idt,
                                           dw=0):
    k_h, k_w = k
    ifm_dim_h, ifm_dim_w = ifm_dim
    stride_h, stride_w = stride
    dilation_h, dilation_w = dilation
    ofm_dim_h, ofm_dim_w = ofm_dim

    odt = idt
    inp = helper.make_tensor_value_info("inp", TensorProto.FLOAT,
                                        [1, ifm_dim_h, ifm_dim_w, ifm_ch])
    outp = helper.make_tensor_value_info(
        "outp", TensorProto.FLOAT,
        [1, ofm_dim_h, ofm_dim_w, k_h * k_w * ifm_ch])

    SlidingWindow_node = helper.make_node(
        "ConvolutionInputGenerator1D",
        ["inp"],
        ["outp"],
        domain="finn.custom_op.fpgadataflow",
        backend="fpgadataflow",
        ConvKernelDim=[k_h, k_w],
        IFMChannels=ifm_ch,
        IFMDim=[ifm_dim_h, ifm_dim_w],
        OFMDim=[ofm_dim_h, ofm_dim_w],
        SIMD=simd,
        Stride=[stride_h, stride_w],
        Dilation=[dilation_h, dilation_w],
        inputDataType=idt.name,
        outputDataType=odt.name,
        depthwise=dw,
    )
    graph = helper.make_graph(
        nodes=[SlidingWindow_node],
        name="slidingwindow_graph",
        inputs=[inp],
        outputs=[outp],
    )

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

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

    return model
Esempio n. 20
0
def test_end2end_mobilenet_export():
    # export preprocessing
    preproc_onnx = build_dir + "/end2end_mobilenet_preproc.onnx"
    mean = [0.485, 0.456, 0.406]
    std = 0.226
    ch = 3
    preproc = NormalizePreProc(mean, std, ch)
    bo.export_finn_onnx(preproc, (1, 3, 224, 224), preproc_onnx)
    preproc_model = ModelWrapper(preproc_onnx)
    # set input finn datatype to UINT8
    preproc_model.set_tensor_datatype(preproc_model.graph.input[0].name,
                                      DataType["UINT8"])
    preproc_model = preproc_model.transform(InferShapes())
    preproc_model = preproc_model.transform(FoldConstants())
    preproc_model = preproc_model.transform(GiveUniqueNodeNames())
    preproc_model = preproc_model.transform(GiveUniqueParameterTensors())
    preproc_model = preproc_model.transform(GiveReadableTensorNames())
    preproc_model.save(build_dir + "/end2end_mobilenet_preproc.onnx")

    # export mobilenet
    finn_onnx = build_dir + "/end2end_mobilenet_export.onnx"
    mobilenet = get_test_model_trained("mobilenet", 4, 4)
    bo.export_finn_onnx(mobilenet, (1, 3, 224, 224), finn_onnx)

    # calculate golden output with pytorch/brevitas and save as .npy
    # get single image as input and prepare image
    img = Image.open("/workspace/finn/tests/brevitas/king_charles.jpg")
    # resize smallest side of the image to 256 pixels and resize larger side
    # with same ratio
    img = resize_smaller_side(256, img)
    # crop central 224*224 window
    img = crop_center(224, img)
    # save image as numpy array and as torch tensor to enable testing in
    # brevitas/pytorch and finn and transpose from (H, W, C) to (C, H, W)
    img_np = np.asarray(img).copy().astype(np.float32).transpose(2, 0, 1)
    img_np = img_np.reshape(1, 3, 224, 224)
    np.save(build_dir + "/end2end_mobilenet_input.npy", img_np)
    img_torch = torch.from_numpy(img_np).float()
    # do forward pass in PyTorch/Brevitas
    input_tensor = preproc.forward(img_torch)
    golden = mobilenet.forward(input_tensor).detach().numpy()
    golden_topk = golden.flatten()
    golden_top5 = np.argsort(golden_topk)[-5:]
    golden_top5 = np.flip(golden_top5)
    golden_top5_prob = []
    for index in golden_top5:
        golden_top5_prob.append(golden_topk[index])
    # save golden output values
    np.save(build_dir + "/end2end_mobilenet_golden_top5.npy", golden_top5)
    np.save(build_dir + "/end2end_mobilenet_golden_top5_prob.npy",
            golden_top5_prob)
    assert os.path.isfile(finn_onnx)
    assert os.path.isfile(build_dir + "/end2end_mobilenet_preproc.onnx")
Esempio n. 21
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
Esempio n. 22
0
def test_infer_datatypes():
    raw_m = get_data("finn.data", "onnx/mnist-conv/model.onnx")
    model = ModelWrapper(raw_m)
    model = model.transform(InferShapes())
    model = model.transform(FoldConstants())
    model = model.transform(GiveUniqueNodeNames())
    model = model.transform(GiveReadableTensorNames())
    # this model has no DataType info, so add some DataType annotation
    # to make things a bit more exciting
    model.set_tensor_datatype("global_in", DataType["UINT8"])
    # Conv with int weights + inputs will have int output datatype
    model.set_tensor_datatype("Conv_0_param0", DataType["INT4"])
    model = model.transform(InferDataTypes())
    assert model.get_tensor_datatype("global_in") == DataType["UINT8"]
    assert model.get_tensor_datatype("Conv_0_out0") == DataType["INT32"]
    assert model.get_tensor_datatype("Relu_0_out0") == DataType["FLOAT32"]
    assert model.get_tensor_datatype("global_out") == DataType["FLOAT32"]
Esempio n. 23
0
def test_move_flatten_past_affine(data_layout, batch_size):
    if data_layout == DataLayout.NHWC:
        ishape = [batch_size, 1, 1, 1024]
        oshape = [batch_size, 1024]
    else:
        ishape = [batch_size, 1024, 1, 1]
        oshape = [batch_size, 1024]

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

    flatten_node = helper.make_node("Flatten", ["inp"], ["outp"])

    graph = helper.make_graph(
        nodes=[flatten_node],
        name="move-flatten-graph",
        inputs=[inp],
        outputs=[outp],
    )

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

    model.set_tensor_datatype("inp", DataType.INT2)
    model.set_tensor_layout("inp", data_layout)
    model = model.transform(InsertTopK())
    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(MoveFlattenPastTopK())
    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
Esempio n. 24
0
def make_single_slidingwindow_modelwrapper(k,
                                           ifm_ch,
                                           ifm_dim,
                                           ofm_dim,
                                           simd,
                                           stride,
                                           idt,
                                           dw=0):
    odt = idt
    inp = helper.make_tensor_value_info("inp", TensorProto.FLOAT,
                                        [1, ifm_dim, ifm_dim, ifm_ch])
    outp = helper.make_tensor_value_info("outp", TensorProto.FLOAT,
                                         [1, ofm_dim, ofm_dim, k * k * ifm_ch])

    SlidingWindow_node = helper.make_node(
        "ConvolutionInputGenerator",
        ["inp"],
        ["outp"],
        domain="finn",
        backend="fpgadataflow",
        ConvKernelDim=k,
        IFMChannels=ifm_ch,
        IFMDim=ifm_dim,
        OFMDim=ofm_dim,
        SIMD=simd,
        Stride=stride,
        inputDataType=idt.name,
        outputDataType=odt.name,
        depthwise=dw,
    )
    graph = helper.make_graph(
        nodes=[SlidingWindow_node],
        name="slidingwindow_graph",
        inputs=[inp],
        outputs=[outp],
    )

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

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

    return model
Esempio n. 25
0
def make_single_fmpadding_modelwrapper(idim, padding, num_ch, simd, idt, pad_style):
    pad_h = padding[0] + padding[2]
    pad_w = padding[1] + padding[3]
    idim_h, idim_w = idim

    assert pad_style == 2, "only pad_style == 2 supported in hlslib"
    assert pad_h > 0 or pad_w > 0, "Output dim should be greater than input dim"
    odim_h = idim_h + pad_h
    odim_w = idim_w + pad_w

    inp = helper.make_tensor_value_info(
        "inp", TensorProto.FLOAT, [1, idim_h, idim_w, num_ch]
    )
    outp = helper.make_tensor_value_info(
        "outp", TensorProto.FLOAT, [1, odim_h, odim_w, num_ch]
    )

    FMPadding = helper.make_node(
        "FMPadding_Batch",
        ["inp"],
        ["outp"],
        domain="finn.custom_op.fpgadataflow",
        backend="fpgadataflow",
        ImgDim=idim,
        Padding=padding,
        NumChannels=num_ch,
        inputDataType=str(idt.name),
        PaddingStyle=pad_style,
        numInputVectors=1,
        SIMD=simd,
    )

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

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

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

    return model
Esempio n. 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
Esempio n. 27
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
Esempio n. 28
0
def step_resnet50_convert_to_hls(model: ModelWrapper,
                                 cfg: DataflowBuildConfig):
    model.set_tensor_datatype(model.graph.input[0].name, DataType["UINT8"])
    model = model.transform(InferDataLayouts())

    try:
        from finn.transformation.fpgadataflow.infer_doublepacked_dsp import InferDoublePackedConv
        model = model.transform(InferDoublePackedConv([1]))
    except:
        print(
            " FINN Experimental not available. Using non-packed convolution ")

    model = model.transform(DoubleToSingleFloat())
    model = model.transform(InferDataTypes())
    model = model.transform(SortGraph())

    to_hls_transformations = [
        to_hls.InferAddStreamsLayer, LowerConvsToMatMul,
        to_hls.InferChannelwiseLinearLayer, to_hls.InferPool_Batch,
        AbsorbTransposeIntoMultiThreshold, RoundAndClipThresholds,
        to_hls.InferQuantizedStreamingFCLayer, to_hls.InferThresholdingLayer,
        AbsorbConsecutiveTransposes, to_hls.InferConvInpGen,
        to_hls.InferDuplicateStreamsLayer, to_hls.InferLabelSelectLayer
    ]
    for trn in to_hls_transformations:
        model = model.transform(trn())
        model = model.transform(InferDataLayouts())
        model = model.transform(GiveUniqueNodeNames())
        model = model.transform(InferDataTypes())

    model = model.transform(RemoveCNVtoFCFlatten())
    model = model.transform(GiveReadableTensorNames())
    model = model.transform(RemoveUnusedTensors())
    model = model.transform(SortGraph())

    return model
Esempio n. 29
0
def test_res_estimate():
    mw = mh = 4
    simd = 1
    pe = 1
    idt = DataType.INT2
    wdt = DataType.INT2
    odt = DataType.INT32
    actval = odt.min()

    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",
        resType="ap_resource_lut()",
        MW=mw,
        MH=mh,
        SIMD=simd,
        PE=pe,
        inputDataType=idt.name,
        weightDataType=wdt.name,
        outputDataType=odt.name,
        ActVal=actval,
        binaryXnorMode=0,
        noActivation=0,
    )
    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)

    model = model.transform(GiveUniqueNodeNames())
    prod_resource_estimation = model.analysis(res_estimation)
    expect_resource_estimation = {
        "StreamingFCLayer_Batch_0": {
            "BRAM_18K": 1,
            'BRAM_efficiency': 0.001736111111111111,
            "LUT": 304.4
        }
    }

    assert check_two_dict_for_equality(
        prod_resource_estimation,
        expect_resource_estimation), """The produced output of
Esempio n. 30
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