cornell-zhang / heterocl

HeteroCL: A Multi-Paradigm Programming Infrastructure for Software-Defined Heterogeneous Computing
https://cornell-zhang.github.io/heterocl/
Apache License 2.0
322 stars 92 forks source link

Bundled bus interface gmem0 failed synthesis #275

Closed chhzh123 closed 3 years ago

chhzh123 commented 4 years ago

Current interface specification can only support one input and one output in the function arguments. If more than one inputs are passed in, HLS will complain.

def test_vitis():
    A = hcl.placeholder((10,), "A")
    W = hcl.placeholder((10,), "W")

    def kernel(A, W):
        B = hcl.compute(A.shape, 
                lambda i: A[i] + 1, "B")
        C = hcl.compute(B.shape,
                lambda i: B[i] + W[i], "C")
        return C

    target = hcl.platform.aws_f1
    target.config(compile="vitis", mode="hw_exe", project="project-vitis.prj")
    s = hcl.create_schedule([A, W], kernel)
    s.to([A, W], target.xcel)
    s.to(kernel.C, target.host)
    s.to(kernel.B, s[kernel.C])
    f = hcl.build(s, target)
    np_A = np.zeros((10,))
    np_W = np.zeros((10,))
    np_C = np.zeros((10,))
    hcl_A = hcl.asarray(np_A)
    hcl_W = hcl.asarray(np_W)
    hcl_C = hcl.asarray(np_C)
    f(hcl_A, hcl_W, hcl_C)

The generated VHLS code is shown below.

extern "C" {
void test(ap_int<32> A[10], ap_int<32> C[10], ap_int<32> W[10]) {
    #pragma HLS INTERFACE m_axi port=A offset=slave bundle=gmem0
    #pragma HLS INTERFACE m_axi port=C offset=slave bundle=gmem0
    #pragma HLS INTERFACE m_axi port=W offset=slave bundle=gmem0
    #pragma HLS INTERFACE s_axilite port=A bundle=control
    #pragma HLS INTERFACE s_axilite port=C bundle=control
    #pragma HLS INTERFACE s_axilite port=W bundle=control
    #pragma HLS INTERFACE s_axilite port=return bundle=control
      ap_int<32> B_pipe_1[10];
      #pragma HLS stream variable=B_pipe_1 depth=1
      #pragma HLS dataflow
      B_i: for (ap_int<32> i = 0; i < 10; ++i) {
        ap_int<32> B_temp;
        B_temp = (A[i] + 1);
        B_pipe_1[i] = B_temp;
      }
      C_i1: for (ap_int<32> i1 = 0; i1 < 10; ++i1) {
        ap_int<32> B_temp1;
        B_temp1 = B_pipe_1[i1];
        C[i1] = ((ap_int<32>)(((ap_int<33>)B_temp1) + ((ap_int<33>)W[i1])));
      }
    }
}

And got the following error.

ERROR: [XFORM 203-711] Bundled bus interface gmem0 failed dataflow checking: it cannot read data in multiple processes.
ERROR: [XFORM 203-711] Bundled bus interface gmem0 has read operations in function:  'Loop_B_i_proc' and 'Loop_C_i1_proc'.
ERROR: [HLS 200-70] Pre-synthesis failed.
hecmay commented 4 years ago

Can you try to bind the weights to different HBM banks?

For example

s.to(A, target.xcel.HBM[0])
s.to(W, target.xcel.HBM[1])
hecmay commented 3 years ago

This should have been fixed in https://github.com/cornell-zhang/heterocl/pull/418. Please reopen the issue if the error still exists.

jorgekoronis commented 2 years ago

I came up with the same error:

My code is very similar to the code posted by @chhzh123. Did you find a solution? I also want to read two input arguments which are pointers to int. I try to read each of them in a separate loop. When I try to use the dataflow pragma within the context containing those 2 loops, then I see this error:

ERROR: [v++ 200-1013] Bundled bus interface gmem failed dataflow checking: it cannot read data in multiple processes. ERROR: [v++ 200-984] Bundled bus interface gmem has read operations in function: 'read_input_Loop_readA_proc' (...) and 'read_input_Loop_readB_proc' (...).

Do you know how to fix it? Thanks

hecmay commented 2 years ago

@jorgekoronis it seems like these two arrays are accessed using the same AXI port, and this is causing an conflict when they are put in the same dataflow region.

You can probably change the bundle name in “pragma HLS interface port=A bundle=gmem0” to bind these two pointers to different AXI port.

jorgekoronis commented 2 years ago

Thanks @hecmay, your suggestion worked.