The input arguments of stypes.LineBuffer is as the following.
shape: size of each dimension of the line buffer (d_0, d_1, ... d_{n-1})
memlens: length of shift memory of each dimension (s_1, ... s_{n-1})
data: source input value of the linebuffer
head_initvals: lists of read index value of shift memory of each dimension (h_1, ... h_{n-1})
tail_initvals: lists of writeindex value of shift memory of each dimension (t_1, ... t_{n-1})
shift_cond: condition of linebuffer shift operation
rotate_conds: lists of the condition of linebuffer rotate operation for each dimesnsion
Linebuffer consists of window registers and shift memories, and its inner status is updated by shift or rotate operation.
The rotate operation of linebuffer is used in cases such as upsampling, and it enables more efficient resource use than increasing the size of the line buffer and realizing it only by shifting operations.
The n-dimension linebuffer (shape=(d_0, d_1..d_{n-1})) has d_0*d_1...*d_{n-1} window registers, and their indices are represented as (0,0,... 0)...(d_0-1, d_1-1,... d_{n-1}-1).
Linebuffer has n-1 different dimensional shift memory from 1 to n-1, and the number of k-dimensional linebuffer is d_k*...*d{n-1}, and their indices are represented as (0, ...0) ... (d_k-1, ... d{n-1}-1).
head/tail are defined for each shift memory dimension. Shift memory is realized by 2-port BRAM, and reads address head and writes address tail. The head/tail value are incremented when the shift memory of its dimension is operated by shift/rotate operation, and reset to zero when its value is over than the memlen value of its dimension.
The following figure represents shape = (1,3,3) linebuffer and its shift/rotate(dim=1,2) operation.
Shift operation writes data value to the top window register, and the value of window registers and shift memory are shifted.
N-dimensional linebuffer has n-1 kind rotate operations, and the head values of shift memory of the specified dimension are written back to the window registers. For example, in k-dimensional rotate operation, the head value of shift memory with index (i_0 ... i_{n-1-k}) is written back to the window register with index(d_0-1, i_0 ... i_{n-1-k}).
On k-dimensional rotate operation, shift memories of k+1 dimension or more are not updated, and shift memories of k-1 or less and the rest window registers are updated as well as the shift operation.
LineBuffer.get_window(index) method can be used to access the window registers of the linebuffer. The input argument index is the tuple of window register index or the int scalar value of the dictionary order of the window register.
implementation
Shift/Rotate operation are performed in 2 clock cycles (pipeline stages). In the first cycle, the head values of all shift memories are read and its value is used for updating window registers and shift memory in the shift/rotate operation in the second cycle.
The shift / rotate operation can be driven every clock in pipeline, but the RAW distance of the shift memory (tail - head) must be 2 or more.
The following figures show the scheduling and the block diagram of the shape=(3,3) linebuffer as example.
testcase
As the example use of stypes.LineBuffer, I add the stream_linebuffer2d, stream_linebuffer2d_2, stream_linebuffer3d test.
stream_linebuffer2d : upsampling test of 2D image from (4,4) to (8,8)
stream_linebuffer2d_2 : linebuffer test to drive shift operation and rotate operation every clock
stream_linebuffer3d : upsampling test of 3D image from (4,4,4) to (4,8,8)
stypes.LineBuffer
The input arguments of stypes.LineBuffer is as the following.
(d_0, d_1, ... d_{n-1})
(s_1, ... s_{n-1})
(h_1, ... h_{n-1})
(t_1, ... t_{n-1})
Linebuffer consists of window registers and shift memories, and its inner status is updated by shift or rotate operation. The rotate operation of linebuffer is used in cases such as upsampling, and it enables more efficient resource use than increasing the size of the line buffer and realizing it only by shifting operations. The n-dimension linebuffer (
shape=(d_0, d_1..d_{n-1})
) hasd_0*d_1...*d_{n-1}
window registers, and their indices are represented as(0,0,... 0)...(d_0-1, d_1-1,... d_{n-1}-1)
.Linebuffer has n-1 different dimensional shift memory from 1 to n-1, and the number of k-dimensional linebuffer is
d_k*...*d{n-1}
, and their indices are represented as(0, ...0) ... (d_k-1, ... d{n-1}-1)
.head/tail
are defined for each shift memory dimension. Shift memory is realized by 2-port BRAM, and reads addresshead
and writes addresstail
. Thehead/tail
value are incremented when the shift memory of its dimension is operated by shift/rotate operation, and reset to zero when its value is over than thememlen
value of its dimension.The following figure represents
shape = (1,3,3)
linebuffer and its shift/rotate(dim=1,2) operation.Shift operation writes
data
value to the top window register, and the value of window registers and shift memory are shifted.N-dimensional linebuffer has n-1 kind rotate operations, and the head values of shift memory of the specified dimension are written back to the window registers. For example, in k-dimensional rotate operation, the head value of shift memory with index
(i_0 ... i_{n-1-k})
is written back to the window register with index(d_0-1, i_0 ... i_{n-1-k})
.On k-dimensional rotate operation, shift memories of k+1 dimension or more are not updated, and shift memories of k-1 or less and the rest window registers are updated as well as the shift operation.
LineBuffer.get_window(index)
method can be used to access the window registers of the linebuffer. The input argumentindex
is the tuple of window register index or the int scalar value of the dictionary order of the window register.implementation
Shift/Rotate operation are performed in 2 clock cycles (pipeline stages). In the first cycle, the head values of all shift memories are read and its value is used for updating window registers and shift memory in the shift/rotate operation in the second cycle.
The shift / rotate operation can be driven every clock in pipeline, but the RAW distance of the shift memory (tail - head) must be 2 or more. The following figures show the scheduling and the block diagram of the
shape=(3,3)
linebuffer as example.testcase
As the example use of stypes.LineBuffer, I add the
stream_linebuffer2d
,stream_linebuffer2d_2
,stream_linebuffer3d
test.