Skip to content

rlc: multi-user RLC kernel, bootrom toolchain fix, tile write-enable timing - #30

Draft
Aquaticfuller wants to merge 4 commits into
mainfrom
feat/rlc-multiuser
Draft

rlc: multi-user RLC kernel, bootrom toolchain fix, tile write-enable timing#30
Aquaticfuller wants to merge 4 commits into
mainfrom
feat/rlc-multiuser

Conversation

@Aquaticfuller

Copy link
Copy Markdown
Member

1. rlc: multi-user RLC kernel with use-case switching

Brings two things onto the multi-group kernel: the packet-assembly restructuring from PR #12
(@zouguoqi), and a multi-user extension on top of it.

Restructuring (PR #12): rlc_send_pkt / ue_status_rpt / pkt_production_and_recycle split
out of the consumer loop, per-packet TestDataStru, DFX counters, rate pacing.

Multi-user: one rlc_context_t per UE — rlc_ctx[NUM_USERS], sized from the data header's
ACTIVE_USER_NUMBER — with per-user list locks and per-user SN/ACK state. Producers route each
PDCP package to rlc_ctx[user_id] (the user_id was already in every descriptor and simply
ignored); consumers own a static subset of the entities. NUM_USERS == 1 reduces exactly to the
single-entity kernel, so TC1 behaviour is unchanged.

This covers TC2 (multi-user peak, 48 UEs, 800 B) from DP Introduction.docx; TC1 stays
selectable. The use case is chosen at build time by which data header is compiled
(M<users>_N<len>_K<pkgs>data_<M>_<N>_<K>.h), so there is one kernel source, not a fork.

Fitted to this branch's core lists, not replacing them

main added explicit producer_core_ids[] / consumer_core_ids[] dispatch (#27), which is
strictly more general than the contiguous PRODUCER_CORE_NUM ranges the multi-user work was
originally written against. The lists are kept as the source of truth:

  • a consumer's share of the entities follows its index in consumer_core_ids[], not
    core_id - PRODUCER_CORE_NUM, so producer/consumer cores need not be contiguous;
  • the UE status task runs on producer_core_ids[0] instead of core 0 — with explicit lists
    core 0 need not be a producer, and gating on it would have dropped the ACK task entirely;
  • producers_finished is removed as redundant: producer_done is already the count of producers
    that have finished (it additionally carries the this_core_done guard, so a slow producer
    cannot be abandoned mid-flight);
  • PRODUCER_CORE_NUM / CONSUMER_CORE_NUM stay as fallbacks for headers generated before the
    lists existed, and as the pacing divisor.

Fixes carried along

  • DATAHEADER now actually reaches rlc.c. It hard-coded #include "../data/data_1_1350_100.h",
    and since every generated header shares the PDCP_PKG_H guard, the per-variant define was a
    silent no-op — K10, K100 and K300 all compiled the same 100-packet dataset (byte-identical
    ELFs). The dead add_library(rlc ...) target is dropped with it: rlc.c needs the per-variant
    define, which a shared library target cannot provide (nothing linked it).
  • PDU_STRIDE. The generator now pads the slot stride to 4 bytes. An 810 B PDU (800 + 10)
    leaves odd slots 2-byte aligned, which traps the word/vector payload copies; stride and copy
    length are now separate (descriptor pkg_length still carries 810).
  • Rate pacing overflow. PRODUCER_CORE_NUM * PDU_SIZE * CPU_FREQENCY overflows int32
    (2·1360·1e9 wraps to 1285701632), so pacing was silently inert. Fixed with 64-bit math but left
    off by default (RLC_ENABLE_PACING=0 keeps the legacy expression verbatim) so existing
    numbers stay comparable — enabling it changes benchmark behaviour and should be a separate call.
  • Optional payload integrity check behind RLC_SELF_CHECK.

2. Don't hardcode ETH toolchain for bootrom compilation (@jpf-h)

Johannes' fix from #25, carried here so it lands on main: the bootrom rule invoked
riscv -riscv64-gcc-9.5.0 …, which only exists on the ETH cluster, so make toolchain builds
could not build the bootrom. Now uses $(GCC_INSTALL_DIR)/bin/riscv32-unknown-elf-*.
Merged with this branch's dependency-list change to the same rule.

3. cachepool_tile: bank_we/bank_req as direct OR-reduce

Behaviour-preserving timing restructuring. bank_we/bank_req were produced by a priority
cascade plus a 4:1 sel_part_idx mux; they are value-identical to direct OR-reduces of the part
bits (the arbiter always selects a write-part when any write exists, else a read-part), so
computing them directly takes the write-enable off the critical-path tail
(data-bank we → meta-write clock-gate). addr/wdata/be still use the mux. Mirrors what
gen_unfolded_data_banks already did.

jpf-h and others added 3 commits August 24, 2026 22:24
The riscv command is not available when building the toolchain using make toolchain.
…ew-part cascade (shorten data-bank we path tail)
Brings the packet-assembly restructuring and the multi-user extension onto
the multi-group kernel, keeping this branch's explicit producer/consumer
core lists as the dispatch mechanism.

Restructuring (originally from PR #12, Huawei):
  rlc_send_pkt / ue_status_rpt / pkt_production_and_recycle split out of the
  consumer loop, per-packet TestDataStru, DFX counters, rate pacing.

Multi-user:
  One rlc_context_t per UE (rlc_ctx[NUM_USERS], sized from the data header's
  ACTIVE_USER_NUMBER), per-user list locks and per-user SN/ACK state.
  Producers route each PDCP package to rlc_ctx[user_id]; consumers own a
  static subset of the entities. NUM_USERS == 1 reduces to the single-entity
  kernel.

Fitted to the core lists rather than replacing them:
  - a consumer's share of the entities follows its index in
    consumer_core_ids[], not core_id - PRODUCER_CORE_NUM, so the roles need
    not be contiguous;
  - the UE status task runs on producer_core_ids[0] instead of core 0, which
    need not be a producer;
  - producers_finished is dropped: producer_done is already the count of
    producers that have finished.

Also: DATAHEADER now actually reaches rlc.c (a hard-coded include shadowed it,
so every K-variant compiled the same dataset); the generator emits
ACTIVE_USER_NUMBER and a 4-byte-aligned PDU_STRIDE (needed for 810 B PDUs,
whose slots would otherwise be misaligned for the vector copies); pacing
overflow fixed behind RLC_ENABLE_PACING (default off); optional payload
self-check behind RLC_SELF_CHECK.

Co-authored-by: zouguoqi <zouguoqi@huawei.com>
@Aquaticfuller Aquaticfuller self-assigned this Aug 24, 2026
The fallback declared producer_core_ids[NUM_PRODUCER_CORES] = {0, 1}: with a
larger PRODUCER_CORE_NUM the array reads past its initializers, so every core
above the second dispatches as neither producer nor consumer and the run goes
silently idle. Headers generated before the core lists existed hit this as soon
as the P/C counts are swept.

Derive contiguous ranges in that mode instead of declaring an array, and route
both modes through rlc_is_producer / rlc_is_consumer / rlc_consumer_index /
rlc_status_core so the entity partition and the status task follow whichever
mode is active.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants