Пример #1
0
 def get_hls_compatible_threshold_tensor(self, orig_thres_matrix):
     ch = self.get_nodeattr("Channels")
     pe = self.get_nodeattr("PE")
     tmem = self.calc_tmem()
     assert ch % pe == 0, "Requirement Channels divisable by PE is violated."
     assert (
         orig_thres_matrix.ndim == 2
     ), """Threshold matrix dimension is
     not as expected (2)."""
     n_thres_steps = orig_thres_matrix.shape[1]
     ret = orig_thres_matrix
     # distribute rows between PEs
     ret = interleave_matrix_outer_dim_from_partitions(ret, pe)
     assert (
         ret.shape[0] == pe
     ), """First dimension after distribution of the
     rows between PEs is not as expected (pe)"""
     assert (
         ret.shape[1] == tmem
     ), """Second dimension after distribution of the
     rows between PEs is not as expected (tmem)"""
     assert (
         ret.shape[2] == n_thres_steps
     ), """Third dimension after distribution of the
     rows between PEs is not as expected (n_thres_steps)"""
     return ret.reshape(1, pe, tmem, n_thres_steps)
 def get_hls_compatible_threshold_tensor(self, orig_thres_matrix):
     ch = self.get_nodeattr("Channels")
     pe = self.get_nodeattr("PE")
     tmem = self.calc_tmem()
     assert ch % pe == 0, "Requirement Channels divisable by PE is violated."
     assert (
         orig_thres_matrix.ndim == 2
     ), """Threshold matrix dimension is
     not as expected (2)."""
     n_thres_steps = orig_thres_matrix.shape[1]
     ret = orig_thres_matrix
     # workaround for vivado_hls threshold bug
     if ret[0][0] == 0:
         ret = np.copy(ret)
         ret[0][0] = 1
         warnings.warn(
             "Setting 0-valued first threshold to 1 to avoid vivado_hls bug"
         )
     # distribute rows between PEs
     ret = interleave_matrix_outer_dim_from_partitions(ret, pe)
     assert (
         ret.shape[0] == pe
     ), """First dimension after distribution of the
     rows between PEs is not as expected (pe)"""
     assert (
         ret.shape[1] == tmem
     ), """Second dimension after distribution of the
     rows between PEs is not as expected (tmem)"""
     assert (
         ret.shape[2] == n_thres_steps
     ), """Third dimension after distribution of the
     rows between PEs is not as expected (n_thres_steps)"""
     return ret.reshape(1, pe, tmem, n_thres_steps)
Пример #3
0
def test_interleave_matrix_outer_dim_from_partitions():
    A = np.eye(10)
    n_parts = 2
    Ax = util.interleave_matrix_outer_dim_from_partitions(A, n_parts)
    part_size = 10 // n_parts
    assert Ax.shape == (n_parts, part_size, 10)
    for r_ind in range(A.shape[0]):
        assert (A[r_ind] == Ax[r_ind % n_parts][r_ind // n_parts]).all()
Пример #4
0
 def get_hls_compatible_threshold_tensor(self, orig_thres_matrix):
     """Convert the original numpy weight matrix orig_weight_matrix into
     a form suitable for passing to the hlslib call:
     * ensure MH % PE == 0
     * for unsigned inputs, ensure thresholds are positive
     * interleave rows between PEs
     * reshape into (PE, TMEM, n_thres_steps) and return
     """
     mh = self.get_nodeattr("NumChannels")
     pe = self.get_nodeattr("PE")
     tmem = mh // pe
     assert mh % pe == 0, "Requirement NumChannels divisable by PE is violated."
     assert (
         orig_thres_matrix.ndim == 2
     ), """Threshold matrix dimension is
     not as expected (2)."""
     n_thres_steps = orig_thres_matrix.shape[1]
     assert n_thres_steps == self.get_nodeattr(
         "numSteps"
     ), "Mismatch in threshold steps"
     if not self.get_input_datatype().signed():
         # ensure all thresholds are nonnegative
         assert (orig_thres_matrix >= 0).all()
     # ensure all thresholds are integer
     assert np.equal(
         np.mod(orig_thres_matrix, 1), 0
     ).all(), "Need int threshold tensor"
     ret = orig_thres_matrix
     # workaround for vivado_hls threshold bug
     if ret[0][0] == 0 and n_thres_steps == 1:
         ret = np.copy(ret)
         ret[0][0] = 1
         warnings.warn(
             "Setting 0-valued first threshold to 1 to avoid vivado_hls bug"
         )
     # ensure channels = mh , duplicating if necessary
     if ret.shape[0] == 1:
         ret = np.tile(ret, (mh, 1))
     assert (
         ret.shape[0] == mh
     ), "Channels of threshold matrix are not as expected (mh)"
     # distribute rows between PEs
     ret = interleave_matrix_outer_dim_from_partitions(ret, pe)
     assert (
         ret.shape[0] == pe
     ), """First dimension after distribution of the
     rows between PEs is not as expected (pe)"""
     assert (
         ret.shape[1] == tmem
     ), """Second dimension after distribution of the
     rows between PEs is not as expected (tmem)"""
     assert (
         ret.shape[2] == n_thres_steps
     ), """Third dimension after distribution of the
     rows between PEs is not as expected (n_thres_steps)"""
     return ret.reshape(1, pe, tmem, n_thres_steps)
Пример #5
0
 def get_hls_compatible_threshold_tensor(self, orig_thres_matrix):
     """Convert the original numpy weight matrix orig_weight_matrix into
     a form suitable for passing to the hlslib call:
     * ensure MH % PE == 0
     * for bipolar weights&inputs, ensure thresholds are positive
     * interleave rows between PEs
     * reshape into (PE, TMEM, n_thres_steps) and return
     """
     mh = self.get_nodeattr("MH")
     pe = self.get_nodeattr("PE")
     tmem = mh // pe
     assert mh % pe == 0, "Requirement MH divisable by PE is violated."
     assert (
         orig_thres_matrix.ndim == 2
     ), """Threshold matrix dimension is
     not as expected (2)."""
     n_thres_steps = orig_thres_matrix.shape[1]
     inp_is_bipolar = self.get_input_datatype() == DataType.BIPOLAR
     wt_is_bipolar = self.get_weight_datatype() == DataType.BIPOLAR
     # reinterpret inp/wt as bipolar if bin_xnor_mode is iset
     inp_is_binary = self.get_input_datatype() == DataType.BINARY
     wt_is_binary = self.get_weight_datatype() == DataType.BINARY
     bin_xnor_mode = self.get_nodeattr("binaryXnorMode") == 1
     inp_is_bipolar = inp_is_bipolar or (inp_is_binary and bin_xnor_mode)
     wt_is_bipolar = wt_is_bipolar or (wt_is_binary and bin_xnor_mode)
     if inp_is_bipolar and wt_is_bipolar:
         # ensure all thresholds are nonnegative
         assert (orig_thres_matrix >= 0).all()
         # ensure all thresholds are integer
         assert (orig_thres_matrix.astype(np.int32) == orig_thres_matrix).all()
     ret = orig_thres_matrix
     # ensure channels = mh , duplicating if necessary
     if ret.shape[0] == 1:
         ret = np.tile(ret, (mh, 1))
     assert (
         ret.shape[0] == mh
     ), "Channels of threshold matrix are not as expected (mh)"
     # distribute rows between PEs
     ret = interleave_matrix_outer_dim_from_partitions(ret, pe)
     assert (
         ret.shape[0] == pe
     ), """First dimension after distribution of the
     rows between PEs is not as expected (pe)"""
     assert (
         ret.shape[1] == tmem
     ), """Second dimension after distribution of the
     rows between PEs is not as expected (tmem)"""
     assert (
         ret.shape[2] == n_thres_steps
     ), """Third dimension after distribution of the
     rows between PEs is not as expected (n_thres_steps)"""
     return ret.reshape(1, pe, tmem, n_thres_steps)
Пример #6
0
 def get_hls_compatible_weight_tensor(self, orig_weight_matrix):
     pe = self.get_nodeattr("PE")
     ch = self.get_nodeattr("Channels")
     k = self.get_nodeattr("Kernel")
     wmem = self.calc_wmem()
     assert orig_weight_matrix.shape == (
         ch,
         1,
         k,
         k,
     ), """Weights matrix doesn't
     have expected shape (channels, 1, kernel_size, kernel_size)"""
     ret = orig_weight_matrix
     ret = ret.reshape(ch, k * k)
     # distribute rows between PEs
     ret = interleave_matrix_outer_dim_from_partitions(ret, pe)
     ret = ret.reshape(1, pe, wmem, 1)
     return ret
Пример #7
0
 def get_hls_compatible_weight_tensor(self, orig_weight_matrix):
     """Convert the original numpy weight matrix orig_weight_matrix into
     a form suitable for passing to the hlslib call:
     * ensure MH % PE == 0 and MW % SIMD == 0
     * for bipolar {-1,+1} weights, convert to binary {0, 1}
     * interleave rows between PEs
     * reshape into (1, PE, WMEM, SIMD) and return
     """
     mw = self.get_nodeattr("MW")
     mh = self.get_nodeattr("MH")
     pe = self.get_nodeattr("PE")
     simd = self.get_nodeattr("SIMD")
     wmem = self.calc_wmem()
     assert orig_weight_matrix.shape == (
         mw,
         mh,
     ), """Weights matrix doesn't
     have expected shape (mw, mh)"""
     assert mw % simd == 0, "Requirement MH divisable by SIMD is violated."
     assert mh % pe == 0, "Requirement MH divisable by PE is violated."
     # start by transposing the original weight matrix, since ONNX and
     # finn-hlslib use different assumptions
     # ONNX uses (in_features, out_features) and matmul(x, W)
     # finn-hlslib uses (out_features, in_features) and matmul(W, x)
     ret = orig_weight_matrix.T
     if self.get_weight_datatype() == DataType.BIPOLAR:
         # convert bipolar to binary
         ret = (ret + 1) / 2
     # interleave rows between PEs and reshape
     # distribute rows between PEs
     ret = interleave_matrix_outer_dim_from_partitions(ret, pe)
     # create SIMD as innermost dimension and add a dummy outer dim
     ret = ret.reshape(1, pe, wmem, simd)
     # reverse the SIMD dimension
     ret = np.flip(ret, axis=-1)
     return ret