Line data Source code
1 : #ifndef HEADER_fd_src_disco_shred_fd_shred_batch_h 2 : #define HEADER_fd_src_disco_shred_fd_shred_batch_h 3 : 4 : #include "../../util/fd_util_base.h" 5 : #include "../shred/fd_shredder.h" 6 : 7 : /* The shred tile partitions a block into batches of microblocks, and 8 : it partitions each batch into fixed-size FEC sets, with 32 data 9 : shreds and 32 parity shreds each. Each batch is made up of an 10 : integer number of microblocks, which means that no microblock can 11 : cross the batch boundary, and that the last FEC set may need to be 12 : padded with 0s. Since padding completes the payload of the last 13 : FEC set in the batch, and does not impact the batch itself, no FEC 14 : set can contain only padding. 15 : The number of FEC sets per batch is limited only by block-level 16 : limits, so the larger the value, the less relative padding overhead 17 : in every batch. However, the larger the value, the longer it takes 18 : before the tile can start generating and sending FEC sets, unless 19 : you use some strange speculative tricks, which we do not use. 20 : Assuming n batches in a given block, the (upper-limit) quantity of 21 : FEC sets is determined by FD_SHRED_BATCH_FEC_SETS_WMARK for the 22 : first n-1 batches, and by FD_SHRED_BATCH_FEC_SETS_MAX for the last 23 : batch. This is needed because when the microblock completing the 24 : block is received, we include it in the current batch irrespective 25 : of how full the batch might be. The diagrams below (not at scale) 26 : show 2 FEC sets before the watermark (W), which indicates where to 27 : close the current batch, as well as 2 extra FEC sets available for 28 : the last batch in the block. 29 : 30 : Normal: (to be deprecated) 31 : +------------+------------+~~~~~~~~~~~+~~~~~~~~~~~~+ 32 : | FEC_set | FEC_set (W) extra | extra | 33 : +------------+------------+~~~~~~~~~~~+~~~~~~~~~~~~+ 34 : 35 : Chained: (first n-1 batches) 36 : +-----------+-----------+~~~~~~~~~~+~~~~~~~~~~~+ 37 : | FEC_set | FEC_set (W) extra | extra | 38 : +-----------+-----------+~~~~~~~~~~+~~~~~~~~~~~+ 39 : 40 : Resigned: (last batch in block) 41 : +----------+----------+~~~~~~~~~~+~~~~~~~~~~+ 42 : | FEC_set | FEC_set (W) extra | extra | 43 : +----------+----------+~~~~~~~~~~+~~~~~~~~~~+ 44 : 45 : The first n-1 batches are chained, whereas the last one in the 46 : block is (chained+)resigned, which means that each shred (and thus 47 : each FEC set) in the last batch has a smaller payload capacity. 48 : In order to size the region labeled extra, we need to consider the 49 : worst case scenario: we have buffered W-1 bytes using the chained 50 : watermark, when a max-size microblock arrives indicating it is the 51 : last in the block. This situation can only happen when running in 52 : low-power mode, because otherwise the last microblock would be a 53 : tick, which is small, but it does not seem to be worth plumbing in 54 : that sort of logic just to save a little memory that would not 55 : pollute cache anyway. 56 : 57 : Note that this payload reduction does not affect normal FEC sets, 58 : which are scheduled to be deprecated at some point (TODO). */ 59 0 : #define FD_SHRED_BATCH_FEC_SETS_WMARK ( 2UL ) 60 0 : #define FD_SHRED_BATCH_FEC_SETS_EXTRA ( 2UL ) 61 : /* FD_SHRED_BATCH_FEC_SETS_MAX affects the value of STEM_BURST inside 62 : the shred tile (refer to its calculation for details). */ 63 0 : #define FD_SHRED_BATCH_FEC_SETS_MAX ( FD_SHRED_BATCH_FEC_SETS_WMARK + FD_SHRED_BATCH_FEC_SETS_EXTRA ) 64 : /* Validate extra payload capacity. Note that (chained+)resigned 65 : needs to take into considerations the watermark regression. */ 66 : #define FD_SHRED_BATCH_RESIGNED_WMARK_REGRESSION ( FD_SHRED_BATCH_FEC_SETS_WMARK * ( FD_SHREDDER_CHAINED_FEC_SET_PAYLOAD_SZ - FD_SHREDDER_RESIGNED_FEC_SET_PAYLOAD_SZ ) ) 67 : FD_STATIC_ASSERT( ( FD_SHRED_BATCH_FEC_SETS_EXTRA * FD_SHREDDER_NORMAL_FEC_SET_PAYLOAD_SZ ) >= ( FD_POH_SHRED_MTU ), FD_SHRED_BATCH_FEC_SETS_EXTRA ); 68 : FD_STATIC_ASSERT( ( FD_SHRED_BATCH_FEC_SETS_EXTRA * FD_SHREDDER_CHAINED_FEC_SET_PAYLOAD_SZ ) >= ( FD_POH_SHRED_MTU ), FD_SHRED_BATCH_FEC_SETS_EXTRA ); 69 : FD_STATIC_ASSERT( ( FD_SHRED_BATCH_FEC_SETS_EXTRA * FD_SHREDDER_RESIGNED_FEC_SET_PAYLOAD_SZ ) >= ( FD_POH_SHRED_MTU + FD_SHRED_BATCH_RESIGNED_WMARK_REGRESSION ), FD_SHRED_BATCH_FEC_SETS_EXTRA ); 70 : 71 : /* FD_SHRED_BATCH_WMARK: Following along the lines of dcache, batch 72 : microblocks until either the slot ends or the batch would exceed 73 : the corresponding watermark. Only when the received microblock 74 : completes the block is the batch allowed to go beyond the given 75 : watermark, since all remaining FEC sets need to be generated and 76 : forwarded at once. The watermark is relative to the beginning 77 : of the payload in the pending batch buffer (i.e. excluding the 78 : 8 bytes needed for microblock_cnt in the batch header). */ 79 0 : #define FD_SHRED_BATCH_WMARK_NORMAL ( FD_SHRED_BATCH_FEC_SETS_WMARK * FD_SHREDDER_NORMAL_FEC_SET_PAYLOAD_SZ - 8UL ) 80 0 : #define FD_SHRED_BATCH_WMARK_CHAINED ( FD_SHRED_BATCH_FEC_SETS_WMARK * FD_SHREDDER_CHAINED_FEC_SET_PAYLOAD_SZ - 8UL ) 81 0 : #define FD_SHRED_BATCH_WMARK_RESIGNED ( FD_SHRED_BATCH_FEC_SETS_WMARK * FD_SHREDDER_RESIGNED_FEC_SET_PAYLOAD_SZ - 8UL ) 82 : /* Validate watermark payload capacity. It must support at least 83 : FD_POH_SHRED_MTU bytes. Prefer > to >= as a safety margin, to 84 : avoid any dependency on how we determine later on if the batch 85 : would exceed the watermark. */ 86 : FD_STATIC_ASSERT( ( FD_SHRED_BATCH_WMARK_NORMAL ) > ( FD_POH_SHRED_MTU ), FD_SHRED_BATCH_WMARK_NORMAL ); 87 : FD_STATIC_ASSERT( ( FD_SHRED_BATCH_WMARK_CHAINED ) > ( FD_POH_SHRED_MTU ), FD_SHRED_BATCH_WMARK_CHAINED ); 88 : FD_STATIC_ASSERT( ( FD_SHRED_BATCH_WMARK_RESIGNED ) > ( FD_POH_SHRED_MTU ), FD_SHRED_BATCH_WMARK_RESIGNED ); 89 : FD_STATIC_ASSERT( ( FD_SHRED_BATCH_WMARK_RESIGNED + FD_SHRED_BATCH_RESIGNED_WMARK_REGRESSION ) == ( FD_SHRED_BATCH_WMARK_CHAINED ), FD_SHRED_BATCH_RESIGNED_WMARK_REGRESSION ); 90 : 91 : /* There are three different raw buffer sizes depending on the FEC 92 : set type: normal, chained, and resigned (see fd_shredder.h for 93 : further details). In order to support all three, we allocate the 94 : largest of them (i.e. normal). TODO once normal FEC sets have 95 : been deprecated, replace NORMAL with CHAINED payload size in the 96 : calculation of FD_SHRED_BATCH_RAW_BUF_SZ below. */ 97 : #define FD_SHRED_BATCH_RAW_BUF_SZ ( FD_SHRED_BATCH_FEC_SETS_MAX * FD_SHREDDER_NORMAL_FEC_SET_PAYLOAD_SZ ) 98 : /* Validate batch raw buffer size. Note that (chained+)resigned 99 : needs to take into considerations the watermark regression. */ 100 : FD_STATIC_ASSERT( ( FD_SHRED_BATCH_RAW_BUF_SZ ) >= ( FD_SHRED_BATCH_WMARK_NORMAL + FD_POH_SHRED_MTU ), FD_SHRED_BATCH_RAW_BUF_SZ ); 101 : FD_STATIC_ASSERT( ( FD_SHRED_BATCH_RAW_BUF_SZ ) >= ( FD_SHRED_BATCH_WMARK_CHAINED + FD_POH_SHRED_MTU ), FD_SHRED_BATCH_RAW_BUF_SZ ); 102 : FD_STATIC_ASSERT( ( FD_SHRED_BATCH_RAW_BUF_SZ ) >= ( FD_SHRED_BATCH_WMARK_RESIGNED + FD_POH_SHRED_MTU + FD_SHRED_BATCH_RESIGNED_WMARK_REGRESSION ), FD_SHRED_BATCH_RAW_BUF_SZ ); 103 : 104 : /* Each block is limited to 32k parity shreds. Since each FEC set 105 : is now guaranteed to contain 32 data shreds and 32 parity shreds, 106 : the maximum number of FEC sets is FEC_SETS_MAX = 1024 (32k/32). 107 : We consider the payload capacity of chained FEC sets as the raw 108 : capacity (which is smaller than normal FEC sets), that means 109 : FEC_SETS_MAX * FD_SHREDDER_CHAINED_FEC_SET_PAYLOAD_SZ, and then 110 : we subtract from there the worst-case overheads from: padding, 111 : watermark regression and batch header. 112 : - OHEAD_PAD (padding overhead): except for the last batch in a 113 : block, each batch typically has FD_SHRED_BATCH_FEC_SETS_WMARK FEC 114 : sets, but can contain as little as one FEC set. However, the 115 : worst case occurs when each batch has two FEC sets, of which the 116 : second one contains a single byte of data and the rest is padding. 117 : In that case, OHEAD_PAD -> 1/2 of the maximum raw capacity, i.e. 118 : ( FEC_SETS_MAX / 2 ) * FD_SHREDDER_CHAINED_FEC_SET_PAYLOAD_SZ. 119 : - OHEAD_REG (watermark regression overhead): this is basically 120 : FD_SHRED_BATCH_FEC_SETS_MAX * 2048 bytes (the difference in 121 : payload size between chained and (chained+)resigned FEC sets). 122 : For FD_SHRED_BATCH_FEC_SETS_MAX = 4, the overhead is 8192 bytes. 123 : - OHEAD_HDR (batch header overhead): this is 8 bytes per batch, 124 : and is maximum when every batch contains 1 FEC set, therefore 125 : FEC_SETS_MAX * 8 = 8192 bytes. 126 : The calculations below assume FD_SHRED_BATCH_FEC_SETS_MAX = 4. */ 127 : FD_STATIC_ASSERT( ( FD_SHRED_BATCH_FEC_SETS_MAX ) == ( 4UL ), FD_SHRED_BATCH_FEC_SETS_MAX ); 128 : /* Define and validate total overhead. */ 129 0 : #define FD_SHRED_BATCH_BLOCK_DATA_OHEAD ( 512UL * FD_SHREDDER_CHAINED_FEC_SET_PAYLOAD_SZ + 8192UL + 8192UL ) 130 : FD_STATIC_ASSERT( ( FD_SHRED_BATCH_BLOCK_DATA_OHEAD ) < ( 1024UL * FD_SHREDDER_CHAINED_FEC_SET_PAYLOAD_SZ ), FD_SHRED_BATCH_BLOCK_DATA_OHEAD ); 131 : /* Define FD_SHRED_BATCH_BLOCK_DATA_SZ_MAX. */ 132 0 : #define FD_SHRED_BATCH_BLOCK_DATA_SZ_MAX ( 1024UL * FD_SHREDDER_CHAINED_FEC_SET_PAYLOAD_SZ - FD_SHRED_BATCH_BLOCK_DATA_OHEAD ) 133 : 134 : #endif /* HEADER_fd_src_disco_shred_fd_shred_batch_h */