PyHDI / veriloggen

Veriloggen: A Mixed-Paradigm Hardware Construction Framework
Apache License 2.0
306 stars 58 forks source link

add stypes.LineBuffer #33

Closed lp6m closed 3 years ago

lp6m commented 3 years ago

stypes.LineBuffer

LineBuffer(shape, memlens, data, head_initvals, tail_initvals, shift_cond, rotate_conds)

The input arguments of stypes.LineBuffer is as the following.

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.

rotate3d_pr

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.