RTLDoc datamover (lkesting/konark) - RTLDoc example
module

hwpe_stream_addressgen_v4

hwpe-stream.bender/git/checkouts/hwpe-stream-d7752ab5ca8011c5/rtl/streamer/hwpe_stream_addressgen_v4.sv:182elaboratedas datamover_top_wrap.i_datamover_top.i_streamer.i_source.i_addressgen
6in
2out
0sub

The hwpe_stream_addressgen_v4 module is used to generate addresses to load or store HWPE-Stream stream. In this version of the address generator, the address is itself carried within a HWPE-Stream, making it easily stallable. The address generator can be used to generate address from a five-dimensional space, which can be visited with configurable strides in all five dimensions.

The multiple loop functionality is partially overlapped by the functionality provided by the microcode processor hwce_ctrl_ucode that can be embedded in HWPEs. The latter is much more flexible and smaller, but less fast.

One iteration is performed per each cycle when enable_i is 1 and the output addr_o stream is ready. presample_i should be 1 in the first cycle in which the address generator can start generating addresses, and no further. The following piece of pseudo-C code resumes the basic functionality provided by the address generator.

hwpe_stream_addressgen_v4(
  int base_addr,                                                          // base address (byte-aligned)
  int d0_len,    int d1_len,    int d2_len,    int d3_len,   int tot_len, // d0..d3,total length (in number of transactions)
  int d0_stride, int d1_stride, int d2_stride, int d3_stride, int d4_stride, // d0..d4 strides (in bytes)
  int *d0_addr,  int *d1_addr,  int *d2_addr,  int *d3_addr,  int *d4_addr,  // d0..d4 addresses (by reference)
  int *d0_cnt,   int *d1_cnt,   int *d2_cnt,   int *d3_cnt,   int *ov_cnt    // d0..d3,overall counters (by reference)
) {
  // A dimension counts dN_cnt from 1 to len_eff(N), so its index is dN_cnt-1
  // running up and len_eff(N)-dN_cnt running down. It is at its last index when:
  at_top(N)    = down(N) ? (*dN_cnt == 1) : (*dN_cnt == len_eff(N));
  // A second length, switched by an outer dimension only: bits at or below N are
  // masked off, which also keeps at_top -> len_eff -> at_top acyclic. tot_len has
  // to account for the shortened sweeps and for the skipped elements.
  len_eff(N)   = (dN_len_last_1h & at_top & ~((2 << N)-1)) ? dN_len_last : dN_len;
  // A second stride, switched by any dimension. A second address stepped next to
  // the first always holds idx*dN_stride_last, so no multiplier is needed.
  use_last(N)  = (dN_last_1h & at_top) != 0;
  addr(N)      = use_last(N) ? *dN_addr_last : *dN_addr;
  step(N)      = down(N) ? -dN_stride      : dN_stride;
  step_last(N) = down(N) ? -dN_stride_last : dN_stride_last;
  advance(N) { *dN_addr += step(N); *dN_addr_last += step_last(N); *dN_cnt += 1; }
  restart(N) { // the dimension directly above N moved
    down(N)       = alternate_1h[N] ? !down(N) : 0;
    *dN_addr      = alt_skip_1h[N] ? *dN_addr      - step(N)      // skip the repeat
                  : down(N)        ? *dN_addr                     // resume from the top
                  :                  0;                           // restart at the bottom
    *dN_addr_last = alt_skip_1h[N] ? *dN_addr_last - step_last(N)
                  : down(N)        ? *dN_addr_last
                  :                  0;
    *dN_cnt       = alt_skip_1h[N] ? 2 : 1;
  }
  reset(N)   { down(N) = 0; *dN_addr = 0; *dN_addr_last = 0; *dN_cnt = 1; }
  // compute current address
  int current_addr = 0;
  int done = 0;
  if (dim_enable_1h & 0x1 == 0) { // 1-dimensional streaming
    current_addr = base_addr + addr(0);
  }
  else if(dim_enable_1h & 0x2 == 0) { // 2-dimensional streaming
    current_addr = base_addr + addr(1) + addr(0);
  }
  else if(dim_enable_1h & 0x4 == 0) { // 3-dimensional streaming
    current_addr = base_addr + addr(2) + addr(1) + addr(0);
  }
  else if(dim_enable_1h & 0x8 == 0) { // 4-dimensional streaming
    current_addr = base_addr + addr(3) + addr(2) + addr(1) + addr(0);
  }
  else { // 5-dimensional streaming
    current_addr = base_addr + *d4_addr + addr(3) + addr(2) + addr(1) + addr(0);
  }
  // update counters and dimensional addresses
  if(*ov_cnt == tot_len) {
    done = 1;
  }
  if((*d0_cnt < len_eff(0)) || (dim_enable_1h & 0x1 == 0)) {
    advance(0);
  }
  else if ((*d1_cnt < len_eff(1)) || (dim_enable_1h & 0x2 == 0)) {
    restart(0); advance(1);
  }
  else if ((*d2_cnt < len_eff(2)) || (dim_enable_1h & 0x4 == 0)) {
    reset(0); restart(1); advance(2);
  }
  else if ((*d3_cnt < len_eff(3)) || (dim_enable_1h & 0x8 == 0)) {
    reset(0); reset(1); restart(2); advance(3);
  }
  else {
    reset(0); reset(1); reset(2); restart(3);
    *d4_addr = *d4_addr + d4_stride;
  }
  *ov_cnt = *ov_cnt + 1;
  return current_addr, done;
}

With a parameter bit clear the matching control fields are ignored, so every extension is off by default and a zero-initialised control struct keeps working.

hwpe_stream_addressgen_v4 input control signals.

Name

Type

Description

base_addr

logic[31:0]

Byte-aligned base address of the stream in the HWPE-accessible memory.

tot_len

logic[31:0]

Total number of transactions in stream; only the TRANS_CNT LSB are actually used.

dN_len

logic[31:0]

dN length in number of transactions (N = 0..3)

dN_stride

logic[31:0]

dN stride in bytes (N = 0..3)

d4_stride

logic[31:0]

d4 stride in bytes

dim_enable_1h

logic[3:0]

One-hot switch to enable 5-d counting (1111), 4-d (0111), 3-d (0011), 2-d (0001), or 1-d (0000).

dN_stride_last

logic[31:0]

Second stride of dimension N, in bytes (N = 0..3).

dN_last_1h

logic[3:0]

Bit j: use dN_stride_last while dimension j is at its last index. 0 turns it off.

dN_len_last

logic[31:0]

Second length of dimension N, in transactions (N = 0..3).

dN_len_last_1h

logic[3:0]

Bit j: use dN_len_last while dimension j is at its last index. Bits at or below N do nothing.

alternate_1h

logic[3:0]

Bit N: dimension N turns around every time dimension N+1 moves.

alt_skip_1h

logic[3:0]

Bit N: with alternate_1h[N], skip the element shared with the previous sweep.

hwpe_stream_addressgen_v4 output flags.

Name

Type

Description

done

logic

1 when the address generation has finished.

Interface

the boundary of hwpe_stream_addressgen_v4 — it instantiates no other module
G m__hwpe_stream_addressgen_v4 hwpe_stream_addressgen_v4 p__addr_o addr_o m__hwpe_stream_addressgen_v4->p__addr_o source p__flags_o flags_o m__hwpe_stream_addressgen_v4->p__flags_o p__enable_i enable_i p__enable_i->m__hwpe_stream_addressgen_v4 p__presample_i presample_i p__presample_i->m__hwpe_stream_addressgen_v4 p__ctrl_i ctrl_i p__ctrl_i->m__hwpe_stream_addressgen_v4
scroll or pinch to zoom · drag to move · click a node to open

The ports stand at the walls of the module frame: input, left · output, right · interface — a slanted green box is a stream or a bus; the wide green line carries its data, and the arrow gives the direction · control — the dashed amber line shows which module controls what · flag / status · no direction. A straight box is a module. A hexagon is a port that goes in two directions. A dashed inner box is a generate block. The dashed white node is the logic of the module itself: the processes that drive or read a control net. The clock, reset, clear and test-mode nets are not in the graph; the chips below the diagram give them.

Clocks

clk_i

Resets

rst_niactive-low

Clears

clear_isynchronous

Ports 8

Inputs 6

DirNameTypeWidth
in clk_i logic 1
in rst_ni logic 1
in enable_i ctrl logic 1
in clear_i logic 1
in presample_i logic 1
in ctrl_i ctrl hwpe_stream_package::ctrl_addressgen_v4_t 652

Outputs 2

DirNameTypeWidth
out addr_o hwpe_stream_intf_stream .source -
out flags_o flag hwpe_stream_package::flags_addressgen_v4_t 1

Parameters 7

NameResolved value
TRANS_CNT32'd32
CNT32'd32
DIM_ENABLE_1H4'b1111
STRIDE_LAST_1H4'b0
LEN_LAST_1H4'b0
ALTERNATE_1H4'b0
ALT_SKIP_1H4'b0

Instantiated by