HAL Architecture Specification
Introduction
The Hardware Abstraction Layer (HAL) provides a software-visible representation of openENOC hardware components and defines a standardized mechanism for accessing their Control and Status Registers (CSRs). The HAL serves as the primary interface between software and hardware, enabling configuration, monitoring, diagnostics, and runtime control of openENOC subsystems.
This document specifies the HAL architecture and CSR organization for the openENOC Switch and the openENOC Endpoint Interface. The described CSR definitions establish a common programming model for software components and serve as the authoritative reference for hardware/software integration.
The application-facing C API, its compatibility contract, and runtime usage are documented in Runtime API Reference.
CSR Specification Methodology
Within this flow, Control and Status Registers are defined using Accellera’s SystemRDL 2.0 as the authoritative specification format for all openENOC hardware components.
For artefact generation, the openENOC toolchain is based on PeakRDL, which processes the SystemRDL description and produces the corresponding CSR-related outputs used throughout the build and verification flow. Since the current PeakRDL implementation does not support all features of the SystemRDL 2.0 standard, CSR definitions are written with this limitation in mind to ensure that the complete register specification can be translated into all required generated artefacts without manual intervention or post-processing.
openENOC Switch Interface HAL Architecture
The openENOC Switch provides frame-forwarding and management functionality within the openENOC system. Software access to switch resources is provided through the openENOC Switch Interface, which exposes a memory-mapped CSR space.
The switch interface HAL defines the software-visible representation of switch functionality and provides a consistent programming model independent of implementation-specific details.
Architecture
The switch interface HAL is organized around a CSR-based management interface that exposes configuration, status, monitoring, and diagnostic functionality. Software components interact with switch resources through register accesses performed over the openENOC Switch Interface. The HAL architecture establishes a clear separation between software-visible behavior and the underlying frame-forwarding implementation, allowing internal switch architectures to evolve while maintaining software compatibility.
A central configuration aspect of the switch interface HAL is the selection of the switch operating mode. In unmanaged mode, the switch operates autonomously and forwarding state is maintained by internal hardware logic. In this mode, the switch may learn forwarding table entries from observed traffic and update its forwarding state without software intervention. In managed mode, forwarding behavior is controlled through software-visible configuration mechanisms exposed by the openENOC Switch Interface. This allows an external processor to populate, update, inspect, or invalidate forwarding table entries according to system-specific requirements.
The operating mode is controlled through switch configuration registers. These registers define whether the switch operates autonomously or under software control, and they provide the foundation for additional management functions such as forwarding table updates, status inspection, diagnostics, and event handling. Status registers expose the current operational state of the switch and allow software to determine whether the switch is active, idle, paused, or operating under a specific management mode.
The default forwarding behavior for frames that do not match any enabled forwarding table entry is defined through a dedicated register containing a destination interface bitmap. This register specifies the set of output interfaces to which unmatched frames shall be forwarded. In managed mode, this mechanism allows unmatched frames to be redirected toward a switch controller implemented on one of the openENOC endpoints. Such frames are delivered to the controller using the standard openENOC Endpoint Interface, preserving the same data-plane abstraction used by other endpoint-to-network communication.
Since forwarding table updates may affect the active forwarding behavior of the switch, the HAL includes a switch-level flow control mechanism used during managed reconfiguration. This mechanism is exposed through a Flow Control Register and allows software to temporarily stop or pause the flow of frames through the switch before modifying forwarding state. After the pause request is issued, software can observe the corresponding status indication to determine when the switch has reached a safe state for table modification.
Once the switch is paused, software may update forwarding table entries through the CSR space without interfering with active frame forwarding. After the update sequence is complete, software releases the pause condition and normal forwarding operation resumes. This mechanism provides a simple and deterministic way to perform controlled forwarding table reconfiguration while avoiding inconsistent lookup behavior during partial updates.
The flow control mechanism described here is local to switch management and should not be confused with link-level or protocol-level flow control. Its purpose is to coordinate software-driven CSR updates with the internal forwarding pipeline of the switch.
In managed mode, the HAL therefore provides both configuration access and operational control over the switch forwarding behavior. In unmanaged mode, the same hardware may operate without software intervention, and the openENOC Switch Interface may be omitted if no external configuration or monitoring functionality is required.
Forwarding Table
A central software-visible structure of the openENOC Switch is the forwarding table, which defines how frames are forwarded based on their destination MAC address. The table is exposed through the CSR space and can be configured by software using the openENOC Switch Interface.
The forwarding table contains entries aligned to a 32-bit data bus. Each forwarding table entry is represented in the CSR space by fields containing a destination MAC address, an N-bit destination interface bitmap, a single enable bit, and padding bits required for alignment to the 32-bit bus width. The destination interface bitmap defines the set of output interfaces to which a matching frame shall be forwarded.
Example forwarding table for an 8-port openENOC Switch
The figure illustrates an example forwarding table for an openENOC Switch with 8 ports. The table contains several representative forwarding rules. Rule (1) defines unicast forwarding of frames with destination address 0x020E0C000011 to the first output interface. Rule (2) represents a disabled unicast rule that remains present in the table but is not applied during forwarding lookup. Rule (3) defines multicast forwarding of frames with destination address 0x030E0C330000 to the first, third, fifth, and seventh output interfaces. Rule (4) defines frame dropping for destination address 0x020E0C123456 by means of an enabled entry with an empty destination interface bitmap. Rule (M) defines the broadcast forwarding rule for frames with destination address 0xFFFFFFFFFFFF.
Register Definitions and CSR Memory Map
The SystemRDL source shown below defines the CSR structure of the openENOC Switch. This source file is the maintained register specification used by the PeakRDL-based generation flow.
1// SPDX-FileCopyrightText: 2026 Enio Kaljic
2// SPDX-License-Identifier: CERN-OHL-S-2.0
3
4regfile openenoc_switch_interface #(
5 longint unsigned NUM_OF_INTERFACES = 1,
6 longint unsigned TABLE_DEPTH = 1,
7 string INST_NAME = "openenoc_switch_interface"
8) {
9 name = INST_NAME;
10 desc = "Control and status register file for an openENOC Switch instance. It includes configuration registers and a forwarding table used to map destination MAC address keys to output interface selections for frame forwarding.";
11
12 default accesswidth = 32;
13 default regwidth = 32;
14 default alignment = 4;
15
16 reg info {
17 name = {INST_NAME, ".info"};
18 desc = "Read-only information register for this openENOC Switch instance.";
19
20 field {
21 name = {INST_NAME, ".info.num_of_interfaces[21:16]"};
22 desc = "Number of interfaces in this openENOC Switch instance. This field reflects the NUM_OF_INTERFACES parameter value.";
23
24 sw = r;
25 hw = r;
26 } num_of_interfaces[21:16] = NUM_OF_INTERFACES;
27
28 field {
29 name = {INST_NAME, ".info.table_depth[15:0]"};
30 desc = "Depth of the forwarding table in this openENOC Switch instance. This field reflects the TABLE_DEPTH parameter value.";
31
32 sw = r;
33 hw = r;
34 } table_depth[15:0] = TABLE_DEPTH;
35 } info;
36
37 reg forwarding_control {
38 name = {INST_NAME, ".forwarding_control"};
39 desc = "Forwarding control register for the openENOC Switch instance.";
40
41 field {
42 name = {INST_NAME, ".forwarding_control.operation_mode[0:0]"};
43 desc = "Mode of operation for the openENOC Switch instance. When set to 1, the switch operates in managed mode, allowing software to configure the forwarding table and control forwarding operations. When set to 0, the switch operates in unmanaged mode, where forwarding state is maintained autonomously by internal hardware logic without software intervention.";
44
45 sw = rw;
46 hw = r;
47 } operation_mode[0:0] = 0;
48
49 field {
50 name = {INST_NAME, ".forwarding_control.pause_request[7:7]"};
51 desc = "Pause request for the forwarding logic. When set, this field requests the switch to pause frame forwarding and clear its internal pipeline before forwarding table updates are performed.";
52
53
54 sw = rw;
55 hw = r;
56 } pause_request[7:7] = 0;
57
58 field {
59 name = {INST_NAME, ".forwarding_control.pause_done[15:15]"};
60 desc = "Pause done status. When set, this field indicates that the switch has paused frame forwarding and reached a safe state for forwarding table modification.";
61
62 sw = r;
63 hw = w;
64 } pause_done[15:15];
65 } forwarding_control;
66
67 reg default_forwarding {
68 name = {INST_NAME, ".default_forwarding"};
69 desc = "Defines the destination interface or interfaces for frames that do not match any enabled forwarding table entry.";
70
71 field {
72 name = {INST_NAME, ".default_forwarding.bitmap[NUM_OF_INTERFACES-1:0]"};
73 desc = "Bitmap selecting the output interface or interfaces to which frames that do not match any enabled forwarding table entry are forwarded. Bit NUM_OF_INTERFACES-1, the MSB, corresponds to the first interface; bit 0 corresponds to the last interface.";
74
75 sw = rw;
76 hw = r;
77 } bitmap[NUM_OF_INTERFACES-1:0] = 0;
78 } default_forwarding;
79
80 external regfile forwarding_table {
81 name = {INST_NAME, ".forwarding_table"};
82 desc = "Forwarding table used to map MAC addresses to output interface selections for frame forwarding.";
83
84 regfile entry {
85 name = {INST_NAME, ".forwarding_table.entry[0..TABLE_DEPTH-1]"};
86 desc = "Forwarding table entry containing the MAC address key, output interface selection, and entry configuration.";
87
88 reg mac_address {
89 name = {INST_NAME, ".forwarding_table.entry[0..TABLE_DEPTH-1].mac_address"};
90 desc = "48-bit destination MAC address used as the key for this forwarding table entry.";
91
92 regwidth = 64;
93
94 field {
95 name = {INST_NAME, ".forwarding_table.entry[0..TABLE_DEPTH-1].mac_address.hi_word[47:32]"};
96 desc = "Upper 16 bits [47:32] of the 48-bit MAC address stored in this forwarding table entry.";
97
98 sw = rw;
99 hw = rw;
100 } hi_word[47:32];
101
102 field {
103 name = {INST_NAME, ".forwarding_table.entry[0..TABLE_DEPTH-1].mac_address.lo_word[31:0]"};
104 desc = "Lower 32 bits [31:0] of the 48-bit MAC address stored in this forwarding table entry.";
105
106 sw = rw;
107 hw = rw;
108 } lo_word[31:0];
109 } mac_address;
110
111 reg iface {
112 name = {INST_NAME, ".forwarding_table.entry[0..TABLE_DEPTH-1].iface"};
113 desc = "Forwarding interface information associated with this forwarding table entry.";
114
115 field {
116 name = {INST_NAME, ".forwarding_table.entry[0..TABLE_DEPTH-1].iface.bitmap[NUM_OF_INTERFACES-1:0]"};
117 desc = "Bitmap selecting the output interface or interfaces to which a matching frame is forwarded. Bit NUM_OF_INTERFACES-1, the MSB, corresponds to the first interface; bit 0 corresponds to the last interface.";
118
119 sw = rw;
120 hw = rw;
121 } bitmap[NUM_OF_INTERFACES-1:0];
122 } iface;
123
124 reg conf {
125 name = {INST_NAME, ".forwarding_table.entry[0..TABLE_DEPTH-1].conf"};
126 desc = "Configuration information associated with this forwarding table entry.";
127
128 field {
129 name = {INST_NAME, ".forwarding_table.entry[0..TABLE_DEPTH-1].conf.enabled"};
130 desc = "Enables this forwarding table entry. When cleared, the entry is ignored during forwarding table lookup.";
131
132 sw = rw;
133 hw = rw;
134 } enabled;
135 } conf;
136 } entry[TABLE_DEPTH];
137 } forwarding_table;
138};
139
140addrmap openenoc_switch_interface_top {
141 name = "openenoc_switch_interface_top";
142 desc = "Control and status address map for an openENOC Switch instance.";
143
144 littleendian;
145 default accesswidth = 32;
146 default regwidth = 32;
147 default alignment = 4;
148 addressing = regalign;
149
150 openenoc_switch_interface #(
151 .NUM_OF_INTERFACES(1),
152 .TABLE_DEPTH(1),
153 .INST_NAME("openenoc_switch_interface")
154 ) openenoc_switch_interface;
155};
The openENOC Switch CSR memory map and detailed register documentation are derived directly from this SystemRDL specification. The generated CSR documentation provides the corresponding human-readable description of the register hierarchy, address offsets, field layouts, access permissions, reset values, and associated register semantics.
The complete generated CSR documentation is available in openenoc_switch_interface_top address map.
openENOC Endpoint Interface HAL Architecture
The openENOC Endpoint Interface provides the connection between processing elements and the openENOC network. It exposes endpoint control, status monitoring, and communication management functionality through a dedicated CSR space.
The endpoint interface HAL establishes a uniform software interface for accessing endpoint resources and controlling interactions with the network.
Architecture
The endpoint interface HAL is organized around a CSR-based management interface that exposes endpoint configuration, software-visible stream access, remote peer configuration, DMA control, and a virtual remote-memory region. Software components interact with endpoint resources through register accesses performed over the openENOC Switch Interface. The HAL architecture establishes a clear separation between software-visible endpoint behavior and the underlying oETP frame handling, allowing internal buffering, DMA scheduling, and protocol processing logic to evolve while maintaining software compatibility.
A central configuration aspect of the endpoint interface HAL is the description of the local endpoint instance and the set of remote peers that it can access. The read-only information register exposes implementation parameters such as the total depth of the virtual remote-memory region and the number of supported remote peers. These values allow software to discover the size and structure of the endpoint address space without relying on hard-coded assumptions.
The endpoint configuration registers define the local unicast MAC address and a separate multicast destination address. The oETP receive filter compares an individual destination against conf.mac_address and a group destination against conf.multicast_address. All endpoints in a replication group configure the same multicast address while retaining individual unicast identities; outgoing oETP frames use the unicast address as their source. A zero multicast address disables oETP group reception. The multicast register follows the unicast MAC register, with both response-timeout registers following the non-oETP receive policy. This destination filtering will be implemented in the oETP engine.
Remote communication targets are described through a peer table, where each entry contains the MAC address of a remote peer, the offset of the corresponding virtual remote-memory region, the local memory base address, the remote memory base address, and the size of the region. This structure allows software to describe how local memory resources are related to remote memory regions visible through the endpoint.
The HAL supports two complementary access models. The first model is a software-visible AXI4-Stream access path exposed through source and sink register files. The source register file allows software to provide stream data words, assert the corresponding valid indication, and mark the last word of a frame. Software observes the ready status to determine when the endpoint can accept the next transfer. Conversely, the sink register file allows hardware to present received stream data to software, together with valid and last indications, while software acknowledges reception through the ready control field.
This CSR-mapped AXI4-Stream interface mirrors the basic AXI4-Stream handshake semantics in software-visible form. It is useful for low-bandwidth communication, diagnostics, initialization sequences, and simple software-driven frame exchange. The mechanism does not prescribe the internal implementation of the endpoint datapath; it only defines how stream-oriented transfers are exposed through the HAL.
The second access model is memory-oriented communication through the virtual remote-memory region. This region provides a software-visible address space representing memory associated with one or more remote peers. The mapping between a remote peer and its corresponding portion of the virtual memory space is defined by the peer configuration registers. Accesses to this region may be handled directly or used as the basis for DMA-driven transfers, depending on the configured DMA mode for the selected peer.
The response-timeout configuration uses two 32-bit cycle counts: conf.rmem_timeout.cycles for transparent RMEM and conf.dma_timeout.cycles for individual unicast peer DMA fragments. The DMA setting is shared by all peers; there is no separate whole-transfer timeout. Both reset to zero, which permits an indefinite response wait. A DMA fragment timeout aborts the remaining fragments and reports peer DMA error code 8 (TIMEOUT). Software controls recovery and any restart; hardware does not retransmit automatically. Multicast writes complete locally without waiting for responses. These CSRs define the oETP timeout policy; runtime enforcement is part of the forthcoming oETP engine implementation.
An RMEM read timeout returns 0xFFFFFFFF with cpuif_rd_ack; an RMEM write timeout asserts cpuif_wr_ack. The existing generated external-RMEM boundary carries ACK and read data and remains unchanged without ERR signals. Transparent RMEM (peer mode 1) and bulk DMA share peers.entry[].dma.error and the four-bit error_code. Local timeout records code 8; a received ERROR_RSP requires an explicit wire-to-CSR code mapping. Starting or successfully completing another operation preserves the error. Writing one to the peer’s dma.clear_error clears the flag and code; hardware acknowledges by clearing the command field. New failures take precedence over a simultaneous clear. The command does not abort active work, clear done, or complete an IRQ claim.
Failure reporting also covers received requests. The responder identifies the
peer by source MAC and records the servicing failure before exposing its failed
completion to the oETP engine. The initiator maps the valid ERROR_RSP cause to
remote code 9..15. An AXI write SLVERR therefore records local code 6 at the
responder and remote code 14 at the initiator. Received failures preserve the
responder’s locally initiated dma.request, idle, and done state;
successful incoming requests preserve sticky errors and generate no IRQ.
An incomplete received DMA_WRITE_REQ or DMA_READ_RSP, including missing or
incorrect EndOfData, records remote code 10 directly. A truncated received
write returns ERROR_RSP wire cause 2, while its receiver retains CSR code 10.
Both endpoints can independently notify software that destination memory may
be partially updated. Multicast receivers retain local diagnostics and enabled
events while suppressing responses.
RMEM and bulk DMA retain separate IRQ sources: irq.event_enable.rmem_error
enables source 5 for RMEM failures, while bulk DMA retains PEER_DMA_COMPLETE,
source 0, gated by the per-peer dma.irq_enable and global
irq.event_enable.peer_dma_complete. For a received bulk failure, the
per-peer enable is captured when recording the error and the global enable
is sampled at IRQ admission. Received RMEM failures use the separate global
RMEM gate at admission. Error recording is independent of IRQ enable; neither
releasing an RMEM access nor returning an error completion waits for IRQ FIFO
capacity. The responder retains a pending notification and defers its next
incoming request until the notification is admitted and committed. Clearing
the CSR error and completing an IRQ claim remain independent operations.
The DMA engine owns the shared status and receives tagged RMEM error completions on the common transfer interface. Both RMEM CPUIF directions and the RMEM IRQ producer belong to that engine. The locally initiating CPUIF transaction controller and its event generation remain to be implemented; the existing scalar CSR stub is retained. The responder already records incoming failures and emits the appropriate error event, including unsupported RMEM requests. The oETP engine owns protocol framing and response timeouts; its parser and ERROR_RSP assembly remain to be implemented.
For non-oETP DMA, AXIS between the engines carries the complete raw Ethernet
frame without FCS. For oETP bulk DMA, it streams exactly the requested memory
bytes without headers, EndOfData, or padding, starting on the first matching
TVALID. The oETP engine appends the 32-bit 0xE0D0E0D0 EndOfData only after
successful final read completion; failures finish the frame without that
marker. The common oETP fragment maximum is 8160 bytes at the unchanged
8192-byte raw Ethernet frame limit. Final TX and late RX protocol outcomes
must be added to the internal transfer contract when implementing the parser.
Address and Length are command metadata, and RMEM data travels directly on
command/completion fields. Internal AXIS TUSER[0] retains the final-fragment
flag; TUSER[1] distinguishes initiator (0) from responder (1) when both
command paths use the same peer and sequence. This adds no software-visible
mode or wire field. The full contract is described in oETP Engine – openenoc_endpoint_oetp_engine.
MAX_RAW_FRAME_SIZE remains a synthesis-time endpoint RDL parameter and
defaults to 8192 bytes without FCS. The read-only
info.max_dma_frame_size_bytes advertises that raw frame ceiling. The global
conf.dma_max_fragment_size.bytes register follows conf.dma_timeout
and selects the maximum memory bytes per locally initiated peer DMA fragment.
Its reset and upper bound are 4 * floor((MAX_RAW_FRAME_SIZE - 32) / 4),
or 8160 bytes in the default build. Hardware rounds the written value down to
a multiple of four, then requires an effective MFS from four through that bound.
The CSR retains the original value: 31 selects 28, 7 selects four, and 8163
selects 8160. Values zero through three or a rounded value above the bound
reject a new DMA block with local error code 1. The final fragment retains the
exact remaining Length, even if it is shorter than four bytes.
The DMA engine snapshots the effective MFS at whole-transfer acceptance, so writes
during a transfer affect only later blocks. Received requests use the physical
fragment ceiling; raw non-oETP DMA, direct CSR streams, and RMEM are unaffected.
DMA behavior is controlled independently for each peer. When DMA operation is disabled, the peer entry remains configured but no automatic transfer is performed. In transparent mode, accesses to the virtual remote-memory region are translated into corresponding accesses to the remote peer memory region on a word-by-word basis. This mode is suitable when software requires a direct memory-mapped view of remote resources and when simple access semantics are preferred over bulk synchronization.
The endpoint interface HAL also supports mirrored transfer modes. In mirror-to-local mode, the local memory region is used as the software-visible representation of the remote peer memory, and the state of the remote memory region is fetched from the remote peer on demand or periodically. In mirror-to-remote mode, the remote memory region is used as the destination representation, and the state of the local memory region is sent to the remote peer on demand or periodically. These modes allow software to configure endpoint-to-endpoint memory synchronization without directly managing individual transport frames.
DMA transfers are initiated through a peer-specific request field. The corresponding status fields indicate whether the DMA engine is idle, whether the requested transfer has completed successfully, or whether an error has occurred. A typical software sequence therefore consists of configuring the peer address mapping, selecting the DMA mode, issuing a transfer request, and observing the idle, done, and error status indications until the operation reaches a terminal state.
Peer DMA error status distinguishes locally detected causes 1..7, local TIMEOUT = 8, and remote causes 9..15 reported through ERROR_RSP. Code 10 also directly identifies an incomplete received DMA data frame or absent/incorrect EndOfData, without requiring ERROR_RSP first. Wire causes 1..7 map to the remote CSR range by adding 8 after validating the complete 32-bit value. Local AXI read/write SLVERR and DECERR use codes 4..7; their remote equivalents use 12..15. Invalid wire causes report local invalid-parameter code 1. The initiator completion interface carries this final encoding, which the DMA engine preserves for both RMEM and bulk DMA. Raw non-oETP DMA error status describes local work. RMEM failure handling is described in oETP Engine – openenoc_endpoint_oetp_engine.
Non-oETP TX and RX each expose command_status.clear_errors at bit 9.
Writing one clears that channel’s error and error_code; hardware clears
the command after accepting it. Starting or successfully completing another
transfer preserves a recorded error, and a new failure takes precedence over a
simultaneous clear. Clearing leaves an active or armed transfer, done, byte
counts, and IRQ events intact. TX, RX, and per-peer error records clear independently.
The DMA control mechanism described here is local to endpoint management and should not be confused with Ethernet link-level or protocol-level flow control. Its purpose is to coordinate software-visible memory mappings and transfer requests with the internal endpoint datapath, DMA engine, and oETP processing logic.
The endpoint interface HAL therefore provides both a stream-oriented and a memory-oriented abstraction for communication with the openENOC network. The AXI4-Stream register interface offers a simple CSR-accessible path for direct frame exchange, while the peer table, virtual remote-memory region, and DMA controls provide a scalable mechanism for accessing and synchronizing memory resources across endpoints.
Register Definitions and CSR Memory Map
The SystemRDL source shown below defines the CSR structure of the openENOC Endpoint Interface. This source file is the maintained register specification used by the PeakRDL-based generation flow.
1// SPDX-FileCopyrightText: 2026 Enio Kaljic
2// SPDX-License-Identifier: CERN-OHL-S-2.0
3
4regfile openenoc_endpoint_interface #(
5 longint unsigned RMEM_TOTAL_DEPTH = 256,
6 longint unsigned NUM_OF_PEERS = 1,
7 longint unsigned MAX_RAW_FRAME_SIZE = 8192,
8 longint unsigned HAS_PEER_DMA = 1,
9 longint unsigned HAS_NON_OETP_DMA = 1,
10 longint unsigned HAS_DIRECT_AXIS = 1,
11 longint unsigned HAS_RMEM = 1,
12 longint unsigned HAS_IRQ = 1,
13 string INST_NAME = "openenoc_endpoint_interface"
14) {
15 name = INST_NAME;
16 desc = "Control and status register file for an openENOC Endpoint Interface instance.";
17
18 default accesswidth = 32;
19 default regwidth = 32;
20 default alignment = 4;
21
22 reg info {
23 name = {INST_NAME, ".info"};
24 desc = "Read-only information register for this openENOC Endpoint Interface instance.";
25
26 regwidth = 64;
27
28 field {
29 name = {INST_NAME, ".info.rmem_total_depth[31:0]"};
30 desc = "Total depth of the shared memory region for all remote peers. This field
31 reflects the RMEM_TOTAL_DEPTH parameter value.";
32
33 sw = r;
34 hw = r;
35 } rmem_total_depth[31:0] = RMEM_TOTAL_DEPTH;
36
37 field {
38 name = {INST_NAME, ".info.num_of_peers[42:32]"};
39 desc = "Number of remote peers supported by this openENOC Endpoint Interface instance,
40 from 0 to 2047. This field reflects the NUM_OF_PEERS parameter value.";
41
42 sw = r;
43 hw = r;
44 } num_of_peers[42:32] = NUM_OF_PEERS;
45
46 field {
47 name = {INST_NAME, ".info.peer_dma_supported"};
48 desc = "Indicates whether DMA transfers associated with configured remote peers are
49 supported.";
50
51 sw = r;
52 hw = r;
53 } peer_dma_supported[43:43] = HAS_PEER_DMA;
54
55 field {
56 name = {INST_NAME, ".info.non_oetp_dma_supported"};
57 desc = "Indicates whether endpoint-level DMA transfers of complete non-oETP Ethernet
58 frames are supported.";
59
60 sw = r;
61 hw = r;
62 } non_oetp_dma_supported[44:44] = HAS_NON_OETP_DMA;
63
64 field {
65 name = {INST_NAME, ".info.direct_axis_supported"};
66 desc = "Indicates whether direct CSR-driven AXI4-Stream access is supported for
67 non-oETP Ethernet frames.";
68
69 sw = r;
70 hw = r;
71 } direct_axis_supported[45:45] = HAS_DIRECT_AXIS;
72
73 field {
74 name = {INST_NAME, ".info.rmem_supported"};
75 desc = "Indicates whether the transparent Remote Memory (RMEM) interface is supported.";
76
77 sw = r;
78 hw = r;
79 } rmem_supported[46:46] = HAS_RMEM;
80
81 field {
82 name = {INST_NAME, ".info.irq_supported"};
83 desc = "Indicates whether the endpoint interrupt output and interrupt-control logic
84 are implemented.";
85
86 sw = r;
87 hw = r;
88 } irq_supported[47:47] = HAS_IRQ;
89
90 field {
91 name = {INST_NAME, ".info.max_dma_frame_size_bytes[63:48]"};
92 desc = "Synthesis-time maximum Ethernet frame size in bytes, excluding FCS. This
93 field reflects the MAX_RAW_FRAME_SIZE parameter value and bounds raw
94 non-oETP DMA frames. The peer DMA memory-fragment ceiling is
95 4 * floor((MAX_RAW_FRAME_SIZE - 32) / 4), accounting for the Ethernet
96 header, oETP write metadata, data-word padding and EndOfData. An 8192-byte
97 frame limit permits 8160-byte memory fragments. A value of zero indicates
98 that DMA is not supported.";
99
100 sw = r;
101 hw = r;
102 } max_dma_frame_size_bytes[63:48] = MAX_RAW_FRAME_SIZE;
103 } info;
104
105 regfile conf {
106 name = {INST_NAME, ".conf"};
107 desc = "Configuration register file for this openENOC Endpoint Interface instance.";
108
109 reg mac_address {
110 name = {INST_NAME, ".conf.mac_address"};
111 desc = "Local endpoint 48-bit unicast MAC address. The oETP engine uses this address
112 as its source MAC and compares individual-addressed incoming oETP frames against
113 it. The I/G bit in the first MAC octet must be zero. Group-addressed oETP frames
114 are compared against conf.multicast_address instead.";
115
116 regwidth = 64;
117
118 field {
119 name = {INST_NAME, ".conf.mac_address.lo_word[31:0]"};
120 desc = "Lower 32 bits [31:0] of the 48-bit MAC address.";
121
122 sw = rw;
123 hw = r;
124 } lo_word[31:0] = 0;
125
126 field {
127 name = {INST_NAME, ".conf.mac_address.hi_word[47:32]"};
128 desc = "Upper 16 bits [47:32] of the 48-bit MAC address.";
129
130 sw = rw;
131 hw = r;
132 } hi_word[47:32] = 0;
133 } mac_address;
134
135 reg multicast_address {
136 name = {INST_NAME, ".conf.multicast_address"};
137 desc = "Local endpoint 48-bit multicast destination MAC address. For an incoming
138 oETP frame whose destination I/G bit is one, the engine accepts the destination
139 only when it exactly matches this address. All slave endpoints in a replication
140 group use the same value. This address is not used as a source MAC. Zero is the
141 reset value and matches no group-addressed destination, disabling oETP group
142 reception. Broadcast is accepted only when this address is all ones. This field
143 does not change the separate non-oETP receive-mode policy.";
144
145 regwidth = 64;
146
147 field {
148 name = {INST_NAME, ".conf.multicast_address.lo_word[31:0]"};
149 desc = "Lower 32 bits [31:0] of the 48-bit multicast MAC address.";
150
151 sw = rw;
152 hw = r;
153 } lo_word[31:0] = 0;
154
155 field {
156 name = {INST_NAME, ".conf.multicast_address.hi_word[47:32]"};
157 desc = "Upper 16 bits [47:32] of the 48-bit multicast MAC address.";
158
159 sw = rw;
160 hw = r;
161 } hi_word[47:32] = 0;
162 } multicast_address;
163
164 reg non_oetp_control {
165 name = {INST_NAME, ".conf.non_oetp_control"};
166 desc = "Receive policy for Ethernet frames that do not carry oETP traffic.";
167
168 field {
169 name = {INST_NAME, ".conf.non_oetp_control.receive_mode[1:0]"};
170 desc = "
171 Receive mode for non-oETP Ethernet frames:<ul>
172 <li>0: Drop all non-oETP Ethernet frames.</li>
173 <li>1: Filtered mode. Accept frames addressed to the configured local MAC
174 address and Ethernet broadcast frames.</li>
175 <li>2: Multicast mode. Accept the same frames as filtered mode, plus all
176 multicast-addressed frames.</li>
177 <li>3: Promiscuous mode. Accept all non-oETP Ethernet frames.</li>
178 </ul>
179 An accepted frame is directed to the non-oETP RX DMA channel when that channel
180 is armed; otherwise it is directed to the CSR AXI4-Stream sink.
181 ";
182
183 sw = rw;
184 hw = r;
185 } receive_mode[1:0] = 1;
186 } non_oetp_control;
187
188 reg rmem_timeout {
189 name = {INST_NAME, ".conf.rmem_timeout"};
190 desc = "Timeout configuration for transparent RMEM operations.";
191
192 field {
193 name = {INST_NAME, ".conf.rmem_timeout.cycles[31:0]"};
194 desc = "Maximum wait for an RMEM response in endpoint clock cycles. Zero disables
195 the timeout and permits an indefinite response wait. Hardware samples this
196 value when it accepts an RMEM operation; subsequent writes apply to later
197 operations. The response timer starts after the complete request frame has
198 been accepted by the Ethernet-facing transmit stream and runs until the
199 complete matching response is received and validated through Ethernet TLAST.
200 RX backpressure counts toward the timeout; remaining local memory completion
201 does not. A valid response completing on the expiry edge takes priority,
202 including a valid ERROR_RSP with its reported cause. Hardware does not
203 retry; timeout handling and retry policy belong to software. Multicast
204 writes do not wait for a response and do not use this response timeout.
205 An RMEM read timeout terminates the access with all-ones read data and read
206 ACK; a write timeout terminates with write ACK. The external-RMEM boundary
207 uses no ERR signals. Failures set error and error_code in the associated
208 peers.entry[].dma register and may generate a separate RMEM_ERROR IRQ event.";
209
210 sw = rw;
211 hw = r;
212 } cycles[31:0] = 0;
213 } rmem_timeout;
214
215 reg dma_timeout {
216 name = {INST_NAME, ".conf.dma_timeout"};
217 desc = "Common response timeout for locally initiated unicast peer DMA fragments.";
218
219 field {
220 name = {INST_NAME, ".conf.dma_timeout.cycles[31:0]"};
221 desc = "Maximum wait for a response to one peer DMA fragment, in endpoint clock
222 cycles. This value is shared by all peers. Zero disables the timeout and
223 permits an indefinite response wait. Hardware samples this value when the
224 oETP engine accepts the fragment request; later writes apply to later
225 fragments. The response timer starts after the complete request frame has
226 been accepted by the Ethernet-facing transmit stream and runs until the
227 complete matching response is received and validated through Ethernet TLAST,
228 including EndOfData where present. RX backpressure counts toward the timeout;
229 remaining local memory completion does not. A valid response completing on
230 the expiry edge takes priority, including a valid ERROR_RSP with its reported
231 cause. On expiry, hardware
232 aborts the remaining fragments of that DMA transfer and reports error code
233 8 (timeout) in the peer DMA status. Hardware does not retry; software decides
234 whether to start another transfer. This timeout does not apply to multicast
235 writes, non-oETP DMA, or transparent RMEM operations.";
236
237 sw = rw;
238 hw = r;
239 } cycles[31:0] = 0;
240 } dma_timeout;
241
242 reg dma_max_fragment_size {
243 name = {INST_NAME, ".conf.dma_max_fragment_size"};
244 desc = "Common software-selected maximum memory fragment size for locally
245 initiated peer DMA transfers. The synthesis-time frame limit remains fixed.";
246
247 field {
248 name = {INST_NAME, ".conf.dma_max_fragment_size.bytes[31:0]"};
249 desc = "Maximum meaningful memory bytes in one locally initiated DMA fragment,
250 excluding Ethernet/oETP headers, word padding, EndOfData and FCS. The
251 hardware rounds the written value down to a multiple of four before
252 validating it. The effective MFS must be at least four bytes and at most
253 4 * floor((MAX_RAW_FRAME_SIZE - 32) / 4). With an 8192-byte frame ceiling,
254 the effective range is 4 through 8160 bytes in steps of four, with reset
255 value 8160. For example, 31 selects 28, 7 selects 4, and 8161 through 8163
256 select 8160. Hardware snapshots the effective value when it accepts the
257 whole peer DMA transfer; later writes apply only to subsequent transfers.
258 The final fragment uses the exact remaining byte length and may be shorter
259 than four bytes. A written value of 0 through 3, or a rounded value above
260 the synthesized ceiling, rejects a new transfer with local error code 1
261 before issuing any memory or protocol operation. The CSR retains the
262 unrounded written value. This setting does not
263 restrict received peer requests, which use the synthesized fragment
264 ceiling, and does not affect RMEM, direct CSR streams or non-oETP DMA.";
265
266 sw = rw;
267 hw = r;
268 } bytes[31:0] = (MAX_RAW_FRAME_SIZE > 32) ?
269 ((MAX_RAW_FRAME_SIZE - 32) / 4) * 4 : 0;
270 } dma_max_fragment_size;
271 } conf;
272
273 regfile axis_if {
274 name = {INST_NAME, ".axis_if"};
275 desc = "Register file for the AXI4-Stream source and sink interfaces.";
276
277 regfile source {
278 name = {INST_NAME, ".axis_if.source"};
279 desc = "Register file for the AXI4-Stream source interface.";
280
281 reg data {
282 name = {INST_NAME, ".axis_if.source.data"};
283 desc = "Data register for the AXI4-Stream source interface.";
284
285 field {
286 name = {INST_NAME, ".axis_if.source.data.tdata[31:0]"};
287 desc = "32-bit data value for the AXI4-Stream source interface.";
288
289 sw = rw;
290 hw = r;
291 } tdata[31:0] = 0;
292 } data;
293
294 reg control {
295 name = {INST_NAME, ".axis_if.source.control"};
296 desc = "Control register for the AXI4-Stream source interface.";
297
298 field {
299 name = {INST_NAME, ".axis_if.source.control.tvalid"};
300 desc = "Indicates that the AXI4-Stream source interface has valid data to send.
301 Once asserted by software, the field remains asserted until the transfer is
302 accepted by the destination.";
303
304 sw = rw;
305 hw = r;
306 hwclr = true;
307 } tvalid[0:0] = 0;
308
309 field {
310 name = {INST_NAME, ".axis_if.source.control.tlast"};
311 desc = "Indicates the last data word of a frame on the AXI4-Stream source
312 interface.";
313
314 sw = rw;
315 hw = r;
316 } tlast[8:8] = 0;
317
318 field {
319 name = {INST_NAME, ".axis_if.source.control.tkeep[3:0]"};
320 desc = "Indicates which byte lanes contain valid data on the AXI4-Stream source
321 interface.";
322
323 sw = rw;
324 hw = r;
325 } tkeep[19:16] = 0;
326 } control;
327
328 reg status {
329 name = {INST_NAME, ".axis_if.source.status"};
330 desc = "Status register for the AXI4-Stream source interface.";
331
332 field {
333 name = {INST_NAME, ".axis_if.source.status.tready"};
334 desc = "Registered readiness at the input of the direct TX AXI4-Stream
335 register slice. With the non_oetp_direct_tx_complete event disabled,
336 follows downstream backpressure through the slice's registered READY
337 path; CSR acknowledgements and frame boundaries do not force it low.
338 With the event enabled, additionally requires frame admission, which
339 reserves space for the TX completion event. Acceptance of the final
340 word (tlast) into the slice deasserts this field until the next frame
341 receives admission. Writing the first word and setting
342 source.control.tvalid requests admission even while this field is low.
343 The active frame retains its admission decision if event_enable changes.
344 Software must retain data, KEEP and LAST until source.control.tvalid
345 is cleared by hardware, independently of this readiness status.";
346
347 sw = r;
348 hw = w;
349 } tready[0:0] = 0;
350 } status;
351 } source;
352
353 regfile sink {
354 name = {INST_NAME, ".axis_if.sink"};
355 desc = "Register file for the AXI4-Stream sink interface.";
356
357 reg data {
358 name = {INST_NAME, ".axis_if.sink.data"};
359 desc = "Data register for the AXI4-Stream sink interface.";
360
361 field {
362 name = {INST_NAME, ".axis_if.sink.data.tdata[31:0]"};
363 desc = "32-bit data value for the AXI4-Stream sink interface.";
364
365 sw = r;
366 hw = w;
367 } tdata[31:0];
368 } data;
369
370 reg control {
371 name = {INST_NAME, ".axis_if.sink.control"};
372 desc = "Control register for the AXI4-Stream sink interface.";
373
374 field {
375 name = {INST_NAME, ".axis_if.sink.control.tready"};
376 desc = "Indicates that the AXI4-Stream sink interface is ready to accept a
377 data transfer. Once asserted by software, the field remains asserted until
378 a transfer occurs.";
379
380 sw = rw;
381 hw = r;
382 hwclr = true;
383 } tready[0:0] = 0;
384 } control;
385
386 reg status {
387 name = {INST_NAME, ".axis_if.sink.status"};
388 desc = "Status register for the AXI4-Stream sink interface.";
389
390 field {
391 name = {INST_NAME, ".axis_if.sink.status.tvalid"};
392 desc = "Indicates that the AXI4-Stream sink interface has valid data
393 to receive.";
394
395 sw = r;
396 hw = w;
397 } tvalid[0:0];
398
399 field {
400 name = {INST_NAME, ".axis_if.sink.status.tlast"};
401 desc = "Indicates the last data word of a frame on the AXI4-Stream
402 sink interface.";
403
404 sw = r;
405 hw = w;
406 } tlast[8:8];
407
408 field {
409 name = {INST_NAME, ".axis_if.sink.status.tkeep[3:0]"};
410 desc = "Indicates which byte lanes contain valid data on the AXI4-Stream
411 sink interface.";
412
413 sw = r;
414 hw = w;
415 } tkeep[19:16];
416 } status;
417 } sink;
418 } axis_if;
419
420 regfile non_oetp_dma {
421 name = {INST_NAME, ".non_oetp_dma"};
422 desc = "Endpoint-level DMA control and status for complete non-oETP Ethernet frames.
423 Frame data includes the Ethernet header and payload, but excludes the preamble,
424 Start Frame Delimiter (SFD), and Frame Check Sequence (FCS).";
425
426 regfile tx {
427 name = {INST_NAME, ".non_oetp_dma.tx"};
428 desc = "Transmit DMA channel for complete non-oETP Ethernet frames.";
429
430 reg buffer_address {
431 name = {INST_NAME, ".non_oetp_dma.tx.buffer_address"};
432 desc = "Local memory address of the non-oETP Ethernet frame to transmit.";
433
434 field {
435 name = {INST_NAME, ".non_oetp_dma.tx.buffer_address.base[31:0]"};
436 desc = "32-bit byte address of the first byte of the transmit buffer.";
437
438 sw = rw;
439 hw = r;
440 } base[31:0] = 0;
441 } buffer_address;
442
443 reg frame_length {
444 name = {INST_NAME, ".non_oetp_dma.tx.frame_length"};
445 desc = "Length of the complete non-oETP Ethernet frame to transmit.";
446
447 field {
448 name = {INST_NAME, ".non_oetp_dma.tx.frame_length.bytes[31:0]"};
449 desc = "Frame length in bytes. Valid non-zero values shall not exceed
450 info.max_dma_frame_size_bytes.";
451
452 sw = rw;
453 hw = r;
454 } bytes[31:0] = 0;
455 } frame_length;
456
457 reg command_status {
458 name = {INST_NAME, ".non_oetp_dma.tx.command_status"};
459 desc = "Command and completion status for the non-oETP transmit DMA channel.";
460
461 field {
462 name = {INST_NAME, ".non_oetp_dma.tx.command_status.request"};
463 desc = "Writing one requests transmission of the configured frame. The field
464 remains asserted until the DMA engine accepts the request. Hardware clears
465 it upon acceptance; while the channel is busy, a newly asserted request
466 remains pending. Software or an RTL controller shall read the completion
467 status and transferred length of the previous request before asserting this
468 field for the next request.";
469
470 sw = rw;
471 hw = r;
472 hwclr = true;
473 } request[8:8] = 0;
474
475 field {
476 name = {INST_NAME, ".non_oetp_dma.tx.command_status.clear_errors"};
477 desc = "Writing one clears this channel's error flag and error code.
478 Hardware clears the command after accepting it. The command does not
479 abort an active transfer, clear done or transferred length, or complete
480 an IRQ claim. A new failure takes precedence over a simultaneous clear.
481 Starting or successfully completing a transfer preserves a recorded error.";
482
483 sw = rw;
484 hw = r;
485 hwclr = true;
486 } clear_errors[9:9] = 0;
487
488 field {
489 name = {INST_NAME, ".non_oetp_dma.tx.command_status.idle"};
490 desc = "Indicates that the channel has no accepted transfer in progress.
491 Hardware deasserts this field when a request is accepted and asserts it
492 when the transfer completes.";
493
494 sw = r;
495 hw = w;
496 } idle[16:16];
497
498 field {
499 name = {INST_NAME, ".non_oetp_dma.tx.command_status.done"};
500 desc = "Sticky successful-completion flag. Hardware sets this field after the
501 accepted transfer completes successfully and clears it when the next request
502 is accepted.";
503
504 sw = r;
505 hw = w;
506 } done[24:24];
507
508 field {
509 name = {INST_NAME, ".non_oetp_dma.tx.command_status.error"};
510 desc = "Sticky error-completion flag. Hardware sets this field when an
511 accepted transfer fails. Only command_status.clear_errors or endpoint
512 reset clears it; starting or successfully completing another transfer
513 preserves a recorded error.";
514
515 sw = r;
516 hw = w;
517 } error[25:25];
518
519 field {
520 name = {INST_NAME, ".non_oetp_dma.tx.command_status.error_code[31:28]"};
521 desc = "
522 Sticky error code for the most recent transmit failure:<ul>
523 <li>0: No error.</li>
524 <li>1: Invalid DMA configuration or descriptor.</li>
525 <li>2: AXI4-Stream length or TLAST error.</li>
526 <li>3: Frame exceeds the supported size or configured buffer capacity.</li>
527 <li>4: AXI read SLVERR response.</li>
528 <li>5: AXI read DECERR response.</li>
529 <li>6: AXI write SLVERR response.</li>
530 <li>7: AXI write DECERR response.</li>
531 <li>8-15: Reserved.</li>
532 </ul>
533 These errors describe local non-oETP DMA work. Only
534 command_status.clear_errors or endpoint reset clears this field.
535 A new failure replaces the code and takes precedence over a simultaneous
536 clear; successful transfers preserve the previous failure.
537 ";
538
539 sw = r;
540 hw = w;
541 } error_code[31:28];
542 } command_status;
543
544 reg transferred_length {
545 name = {INST_NAME, ".non_oetp_dma.tx.transferred_length"};
546 desc = "Number of bytes transferred for the most recently accepted transmit
547 request.";
548
549 field {
550 name = {INST_NAME, ".non_oetp_dma.tx.transferred_length.bytes[31:0]"};
551 desc = "Actual number of bytes transferred. Hardware clears this field when
552 the next request is accepted.";
553
554 sw = r;
555 hw = w;
556 } bytes[31:0];
557 } transferred_length;
558 } tx;
559
560 regfile rx {
561 name = {INST_NAME, ".non_oetp_dma.rx"};
562 desc = "Receive DMA channel for complete non-oETP Ethernet frames.";
563
564 reg buffer_address {
565 name = {INST_NAME, ".non_oetp_dma.rx.buffer_address"};
566 desc = "Local memory address of the receive buffer for a non-oETP Ethernet frame.";
567
568 field {
569 name = {INST_NAME, ".non_oetp_dma.rx.buffer_address.base[31:0]"};
570 desc = "32-bit byte address of the first byte of the receive buffer.";
571
572 sw = rw;
573 hw = r;
574 } base[31:0] = 0;
575 } buffer_address;
576
577 reg buffer_capacity {
578 name = {INST_NAME, ".non_oetp_dma.rx.buffer_capacity"};
579 desc = "Capacity of the receive buffer for one complete non-oETP Ethernet frame.";
580
581 field {
582 name = {INST_NAME, ".non_oetp_dma.rx.buffer_capacity.bytes[31:0]"};
583 desc = "Receive-buffer capacity in bytes. Valid non-zero values shall not exceed
584 info.max_dma_frame_size_bytes.";
585
586 sw = rw;
587 hw = r;
588 } bytes[31:0] = 0;
589 } buffer_capacity;
590
591 reg command_status {
592 name = {INST_NAME, ".non_oetp_dma.rx.command_status"};
593 desc = "Command and completion status for the non-oETP receive DMA channel.";
594
595 field {
596 name = {INST_NAME, ".non_oetp_dma.rx.command_status.request"};
597 desc = "Writing one arms reception into the configured buffer. The field remains
598 asserted until the DMA engine accepts the request. Hardware clears it upon
599 acceptance; while the channel is busy, a newly asserted request remains
600 pending. Software or an RTL controller shall read the completion status and
601 received length of the previous request before asserting this field for the
602 next request.";
603
604 sw = rw;
605 hw = r;
606 hwclr = true;
607 } request[8:8] = 0;
608
609 field {
610 name = {INST_NAME, ".non_oetp_dma.rx.command_status.clear_errors"};
611 desc = "Writing one clears this channel's error flag and error code.
612 Hardware clears the command after accepting it. The command does not
613 abort an active or armed receive, clear done or received length, or
614 complete an IRQ claim. A new failure takes precedence over a simultaneous
615 clear. Starting or successfully completing a transfer preserves a
616 recorded error.";
617
618 sw = rw;
619 hw = r;
620 hwclr = true;
621 } clear_errors[9:9] = 0;
622
623 field {
624 name = {INST_NAME, ".non_oetp_dma.rx.command_status.idle"};
625 desc = "Indicates that the channel has no accepted receive request in progress.
626 After acceptance, the channel may be armed and waiting for an eligible
627 non-oETP frame or may be writing a received frame to memory.";
628
629 sw = r;
630 hw = w;
631 } idle[16:16];
632
633 field {
634 name = {INST_NAME, ".non_oetp_dma.rx.command_status.armed"};
635 desc = "Indicates that the accepted receive request is waiting for an eligible
636 non-oETP Ethernet frame. Hardware sets this field when it accepts a request
637 and clears it when the first beat of the selected frame is accepted by the
638 RX DMA datapath. The frame-routing logic uses this field to select the
639 RX DMA path; otherwise an accepted non-oETP frame is directed to the
640 CSR AXI4-Stream sink.";
641
642 sw = r;
643 hw = w;
644 } armed[17:17];
645
646 field {
647 name = {INST_NAME, ".non_oetp_dma.rx.command_status.done"};
648 desc = "Sticky successful-completion flag. Hardware sets this field after a
649 received frame has been written successfully and clears it when the next
650 request is accepted.";
651
652 sw = r;
653 hw = w;
654 } done[24:24];
655
656 field {
657 name = {INST_NAME, ".non_oetp_dma.rx.command_status.error"};
658 desc = "Sticky error-completion flag. Hardware sets this field when an
659 accepted receive fails. Only command_status.clear_errors or endpoint
660 reset clears it; starting or successfully completing another receive
661 preserves a recorded error.";
662
663 sw = r;
664 hw = w;
665 } error[25:25];
666
667 field {
668 name = {INST_NAME, ".non_oetp_dma.rx.command_status.error_code[31:28]"};
669 desc = "
670 Sticky error code for the most recent receive failure:<ul>
671 <li>0: No error.</li>
672 <li>1: Invalid DMA configuration or descriptor.</li>
673 <li>2: AXI4-Stream length or TLAST error.</li>
674 <li>3: Received frame exceeds the configured buffer capacity.</li>
675 <li>4: AXI read SLVERR response.</li>
676 <li>5: AXI read DECERR response.</li>
677 <li>6: AXI write SLVERR response.</li>
678 <li>7: AXI write DECERR response.</li>
679 <li>8-15: Reserved.</li>
680 </ul>
681 Only command_status.clear_errors or endpoint reset clears this field.
682 A new failure replaces the code and takes precedence over a simultaneous
683 clear; successful transfers preserve the previous failure.
684 ";
685
686 sw = r;
687 hw = w;
688 } error_code[31:28];
689 } command_status;
690
691 reg received_length {
692 name = {INST_NAME, ".non_oetp_dma.rx.received_length"};
693 desc = "Length of the most recently received non-oETP Ethernet frame.";
694
695 field {
696 name = {INST_NAME, ".non_oetp_dma.rx.received_length.bytes[31:0]"};
697 desc = "Actual number of frame bytes written to the receive buffer. Hardware
698 clears this field when the next request is accepted.";
699
700 sw = r;
701 hw = w;
702 } bytes[31:0];
703 } received_length;
704 } rx;
705 } non_oetp_dma;
706
707 regfile irq {
708 name = {INST_NAME, ".irq"};
709 desc = "Endpoint-level interrupt control and claim interface. Interrupt events from peer
710 DMA, non-oETP DMA, direct AXI4-Stream transfers, and RMEM failures are serialized
711 through a shared event FIFO.";
712
713 reg control {
714 name = {INST_NAME, ".irq.control"};
715 desc = "Global interrupt-output control and interrupt-controller maintenance requests.";
716
717 field {
718 name = {INST_NAME, ".irq.control.global_enable"};
719 desc = "Enables the physical endpoint IRQ output. Clearing this field masks the
720 output but does not prevent enabled events from being queued. Event capture is
721 controlled by irq.event_enable and, for peer DMA, by the selected peer's
722 dma.irq_enable field.";
723
724 sw = rw;
725 hw = r;
726 } global_enable[0:0] = 0;
727
728 field {
729 name = {INST_NAME, ".irq.control.clear_errors"};
730 desc = "Writing one requests clearing of the sticky irq.status.overflow and
731 irq.status.invalid_complete flags. The field remains asserted until hardware
732 accepts the request and clears it.";
733
734 sw = rw;
735 hw = r;
736 hwclr = true;
737 } clear_errors[8:8] = 0;
738 } control;
739
740 reg event_enable {
741 name = {INST_NAME, ".irq.event_enable"};
742 desc = "Enables generation of individual endpoint IRQ event classes. These fields
743 control event capture; irq.control.global_enable only masks the physical
744 IRQ output.";
745
746 field {
747 name = {INST_NAME, ".irq.event_enable.peer_dma_complete"};
748 desc = "Enables PEER_DMA_COMPLETE events. A peer event is queued only when this
749 field and the selected peer's dma.irq_enable field were both set when the DMA
750 request was accepted. A failed incoming bulk DMA request also generates this
751 event for the peer resolved from the source MAC. For incoming failures,
752 hardware captures the per-peer enable when recording the failure and samples
753 this field at IRQ admission. Successful incoming requests generate no event.
754 CSR error recording and the error response do not wait for IRQ FIFO capacity.";
755
756 sw = rw;
757 hw = r;
758 } peer_dma_complete[0:0] = 0;
759
760 field {
761 name = {INST_NAME, ".irq.event_enable.non_oetp_dma_tx_complete"};
762 desc = "Enables NON_OETP_DMA_TX_COMPLETE events. Hardware samples this field when
763 it accepts a non-oETP transmit DMA request.";
764
765 sw = rw;
766 hw = r;
767 } non_oetp_dma_tx_complete[1:1] = 0;
768
769 field {
770 name = {INST_NAME, ".irq.event_enable.non_oetp_dma_rx_complete"};
771 desc = "Enables NON_OETP_DMA_RX_COMPLETE events. Hardware samples this field when
772 it accepts a non-oETP receive DMA request.";
773
774 sw = rw;
775 hw = r;
776 } non_oetp_dma_rx_complete[2:2] = 0;
777
778 field {
779 name = {INST_NAME, ".irq.event_enable.non_oetp_direct_tx_complete"};
780 desc = "Enables NON_OETP_DIRECT_TX_COMPLETE events. Hardware samples this field when
781 the first beat of a direct transmit frame is accepted from the CSR-facing
782 AXI4-Stream interface. When enabled, the frame start is accepted only after an
783 IRQ FIFO credit has been reserved. The event is generated when the final beat
784 is accepted by the oETP engine.";
785
786 sw = rw;
787 hw = r;
788 } non_oetp_direct_tx_complete[3:3] = 0;
789
790 field {
791 name = {INST_NAME, ".irq.event_enable.non_oetp_direct_rx_available"};
792 desc = "Enables NON_OETP_DIRECT_RX_AVAILABLE events. One event is generated when
793 the first beat of a new direct receive frame becomes valid on the CSR-facing
794 AXI4-Stream interface. When enabled, routing logic does not expose that first
795 TVALID until an IRQ FIFO credit is available, so the event cannot be lost.
796 The event does not depend on TLAST and therefore supports both cut-through and
797 frame-FIFO operation.";
798
799 sw = rw;
800 hw = r;
801 } non_oetp_direct_rx_available[4:4] = 0;
802
803 field {
804 name = {INST_NAME, ".irq.event_enable.rmem_error"};
805 desc = "Enables RMEM_ERROR events for locally initiated RMEM failures, including
806 timeout and an accepted ERROR_RSP, and failed incoming RMEM requests from a
807 resolved peer. Hardware records the associated peer's
808 dma.error and dma.error_code before
809 exposing the event and terminates the failed RMEM access without waiting
810 for IRQ FIFO capacity. For locally initiated failures the enable is sampled
811 when the failure is recorded; incoming failures sample it at IRQ admission.
812 The bulk DMA per-peer irq_enable does not gate RMEM_ERROR.
813 Successful RMEM accesses generate no event.";
814
815 sw = rw;
816 hw = r;
817 } rmem_error[5:5] = 0;
818 } event_enable;
819
820 reg status {
821 name = {INST_NAME, ".irq.status"};
822 desc = "Status of the endpoint IRQ event FIFO and its reservation mechanism.";
823
824 field {
825 name = {INST_NAME, ".irq.status.claim_pending"};
826 desc = "Indicates that at least one valid event is available in irq.claim.";
827
828 sw = r;
829 hw = w;
830 } claim_pending[0:0];
831
832 field {
833 name = {INST_NAME, ".irq.status.credit_full"};
834 desc = "Indicates that all event FIFO credits are occupied by queued claims or
835 reserved for admitted operations. While no credit is available, new
836 interrupt-enabled DMA requests are not accepted and the start of an
837 interrupt-enabled direct AXI4-Stream frame is backpressured.";
838
839 sw = r;
840 hw = w;
841 } credit_full[1:1];
842
843 field {
844 name = {INST_NAME, ".irq.status.overflow"};
845 desc = "Sticky internal-error flag indicating that an enabled event could not be
846 retained. Correct credit reservation, admission control, and AXI4-Stream
847 backpressure make this condition unreachable during normal operation. Clear with
848 irq.control.clear_errors.";
849
850 sw = r;
851 hw = w;
852 } overflow[2:2];
853
854 field {
855 name = {INST_NAME, ".irq.status.invalid_complete"};
856 desc = "Sticky protocol-error flag indicating that irq.complete.valid was accepted
857 while no claim was pending or that the completion token did not match the
858 current claim. No claim is removed on a mismatch. Clear with
859 irq.control.clear_errors.";
860
861 sw = r;
862 hw = w;
863 } invalid_complete[3:3];
864
865 field {
866 name = {INST_NAME, ".irq.status.irq_asserted"};
867 desc = "Reflects the current value of the physical endpoint IRQ output after
868 application of irq.control.global_enable.";
869
870 sw = r;
871 hw = w;
872 } irq_asserted[4:4];
873
874 field {
875 name = {INST_NAME, ".irq.status.fifo_level[7:0]"};
876 desc = "Number of valid claims currently queued in the IRQ event FIFO. Values
877 greater than 255 are reported as 255.";
878
879 sw = r;
880 hw = w;
881 } fifo_level[15:8];
882
883 field {
884 name = {INST_NAME, ".irq.status.reserved_count[7:0]"};
885 desc = "Number of event FIFO credits reserved for admitted DMA operations or direct
886 transmit frames whose events have not yet been queued. Values greater than 255
887 are reported as 255.";
888
889 sw = r;
890 hw = w;
891 } reserved_count[23:16];
892 } status;
893
894 reg claim {
895 name = {INST_NAME, ".irq.claim"};
896 desc = "Read-only view of the event at the head of the IRQ event FIFO. Reading this
897 register has no side effect, and all fields remain stable until a matching
898 irq.complete request removes the claim.";
899
900 field {
901 name = {INST_NAME, ".irq.claim.peer_idx[10:0]"};
902 desc = "Zero-based peer index for a PEER_DMA_COMPLETE or RMEM_ERROR event, in the range 0 through
903 NUM_OF_PEERS-1. The field is not applicable to other event sources and is driven
904 to zero for deterministic readback.";
905
906 sw = r;
907 hw = w;
908 } peer_idx[10:0];
909
910 field {
911 name = {INST_NAME, ".irq.claim.source[3:0]"};
912 desc = "
913 IRQ event source:<ul>
914 <li>0: PEER_DMA_COMPLETE. A peer DMA request completed with either success or
915 error; peer_idx identifies the peer.</li>
916 <li>1: NON_OETP_DMA_TX_COMPLETE. A non-oETP transmit DMA request completed with
917 either success or error.</li>
918 <li>2: NON_OETP_DMA_RX_COMPLETE. A non-oETP receive DMA request completed with
919 either success or error.</li>
920 <li>3: NON_OETP_DIRECT_TX_COMPLETE. The final beat of a direct non-oETP transmit
921 frame was accepted by the oETP engine.</li>
922 <li>4: NON_OETP_DIRECT_RX_AVAILABLE. The first beat of a new direct non-oETP
923 receive frame is available on the CSR-facing AXI4-Stream interface.</li>
924 <li>5: RMEM_ERROR. A locally initiated RMEM operation failed. The cause is
925 recorded in peers.entry[peer_idx].dma; peer_idx identifies the associated peer.</li>
926 <li>6-15: Reserved.</li>
927 </ul>
928 This field is meaningful only when valid is set.
929 ";
930
931 sw = r;
932 hw = w;
933 } source[14:11];
934
935 field {
936 name = {INST_NAME, ".irq.claim.seq[15:0]"};
937 desc = "Monotonically increasing event sequence number, modulo 65536. The sequence
938 number distinguishes otherwise identical claims and protects against stale or
939 repeated completion requests.";
940
941 sw = r;
942 hw = w;
943 } seq[30:15];
944
945 field {
946 name = {INST_NAME, ".irq.claim.valid"};
947 desc = "Indicates that this register contains the valid event at the head of the
948 IRQ event FIFO. When clear, all other claim fields shall be ignored.";
949
950 sw = r;
951 hw = w;
952 } valid[31:31];
953 } claim;
954
955 reg complete {
956 name = {INST_NAME, ".irq.complete"};
957 desc = "Completion request for the current IRQ claim. Software acknowledges an event by
958 copying the complete 32-bit irq.claim value into this register.";
959
960 field {
961 name = {INST_NAME, ".irq.complete.peer_idx[10:0]"};
962 desc = "Peer-index portion of the claim token.";
963
964 sw = rw;
965 hw = r;
966 } peer_idx[10:0] = 0;
967
968 field {
969 name = {INST_NAME, ".irq.complete.source[3:0]"};
970 desc = "Event-source portion of the claim token.";
971
972 sw = rw;
973 hw = r;
974 } source[14:11] = 0;
975
976 field {
977 name = {INST_NAME, ".irq.complete.seq[15:0]"};
978 desc = "Sequence-number portion of the claim token.";
979
980 sw = rw;
981 hw = r;
982 } seq[30:15] = 0;
983
984 field {
985 name = {INST_NAME, ".irq.complete.valid"};
986 desc = "Writing one submits the completion token. The field remains asserted until
987 hardware validates the token and clears it. A matching token removes the current
988 claim and releases its FIFO credit; an invalid token leaves the claim unchanged
989 and sets irq.status.invalid_complete.";
990
991 sw = rw;
992 hw = r;
993 hwclr = true;
994 } valid[31:31] = 0;
995 } complete;
996 } irq;
997
998 regfile peers {
999 name = {INST_NAME, ".peers"};
1000 desc = "Register file for remote peer configuration and memory region information.";
1001
1002 regfile entry {
1003 name = {INST_NAME, ".peers.entry[0..NUM_OF_PEERS-1]"};
1004 desc = "Register file for a single remote peer configuration and memory region
1005 information.";
1006
1007 reg mac_address {
1008 name = {INST_NAME, ".peers.entry[0..NUM_OF_PEERS-1].mac_address"};
1009 desc = "Remote peer 48-bit destination MAC address.";
1010
1011 regwidth = 64;
1012
1013 field {
1014 name = {INST_NAME, ".peers.entry[0..NUM_OF_PEERS-1].mac_address.lo_word[31:0]"};
1015 desc = "Lower 32 bits [31:0] of the 48-bit MAC address.";
1016
1017 sw = rw;
1018 hw = r;
1019 } lo_word[31:0];
1020
1021 field {
1022 name = {INST_NAME, ".peers.entry[0..NUM_OF_PEERS-1].mac_address.hi_word[47:32]"};
1023 desc = "Upper 16 bits [47:32] of the 48-bit MAC address.";
1024
1025 sw = rw;
1026 hw = r;
1027 } hi_word[47:32];
1028 } mac_address;
1029
1030 reg rmem_address {
1031 name = {INST_NAME, ".peers.entry[0..NUM_OF_PEERS-1].rmem_address"};
1032 desc = "Address offset of the virtual memory region corresponding to the remote
1033 peer's memory.";
1034
1035 field {
1036 name = {INST_NAME, ".peers.entry[0..NUM_OF_PEERS-1].rmem_address.offset[31:0]"};
1037 desc = "32-bit byte offset of the virtual memory region corresponding to the
1038 remote peer's memory. The value shall be aligned to a 32-bit word boundary.";
1039
1040 sw = rw;
1041 hw = r;
1042 } offset[31:0];
1043 } rmem_address;
1044
1045 reg local_address {
1046 name = {INST_NAME, ".peers.entry[0..NUM_OF_PEERS-1].local_address"};
1047 desc = "Start address of the local memory region for DMA transfers.";
1048
1049 field {
1050 name = {INST_NAME, ".peers.entry[0..NUM_OF_PEERS-1].local_address.base[31:0]"};
1051 desc = "Word-aligned 32-bit start address of the local memory region for
1052 DMA transfers.";
1053
1054 sw = rw;
1055 hw = r;
1056 } base[31:0];
1057 } local_address;
1058
1059 reg remote_address {
1060 name = {INST_NAME, ".peers.entry[0..NUM_OF_PEERS-1].remote_address"};
1061 desc = "Start address of the remote peer's memory region.";
1062
1063 field {
1064 name = {INST_NAME, ".peers.entry[0..NUM_OF_PEERS-1].remote_address.base[31:0]"};
1065 desc = "Word-aligned 32-bit start address of the remote peer's memory region.";
1066
1067 sw = rw;
1068 hw = r;
1069 } base[31:0];
1070 } remote_address;
1071
1072 reg size {
1073 name = {INST_NAME, ".peers.entry[0..NUM_OF_PEERS-1].size"};
1074 desc = "Size of the remote peer's memory region.";
1075
1076 field {
1077 name = {INST_NAME, ".peers.entry[0..NUM_OF_PEERS-1].size.bytes[31:0]"};
1078 desc = "32-bit size of the remote peer's memory region in bytes.";
1079
1080 sw = rw;
1081 hw = r;
1082 } bytes[31:0];
1083 } size;
1084
1085 reg dma {
1086 name = {INST_NAME, ".peers.entry[0..NUM_OF_PEERS-1].dma"};
1087 desc = "DMA/RMEM configuration and control for the remote peer, with shared
1088 sticky error reporting. RMEM and bulk DMA retain separate IRQ event classes.";
1089
1090 field {
1091 name = {INST_NAME, ".peers.entry[0..NUM_OF_PEERS-1].dma.mode[1:0]"};
1092 desc = "
1093 DMA mode and responder access policy for the remote peer:<ul>
1094
1095 <li>0: Disabled. Locally initiated DMA and transparent RMEM
1096 operations are disabled, and incoming oETP memory requests from
1097 this peer are rejected.</li>
1098
1099 <li>1: Transparent RMEM mode. Accesses to the virtual RMEM region
1100 are translated into individual remote memory accesses. Incoming
1101 transparent RMEM read and write requests from this peer are
1102 permitted. Bulk DMA read and write requests are rejected.</li>
1103
1104 <li>2: Mirror-to-local mode. A locally initiated DMA request fetches
1105 the remote memory region into the configured local memory region
1106 using remote DMA reads. On the responder side, incoming bulk DMA
1107 write requests from this peer are permitted and target the
1108 configured local memory region. Incoming bulk DMA read requests
1109 are rejected.</li>
1110
1111 <li>3: Mirror-to-remote mode. A locally initiated DMA request sends
1112 the configured local memory region to the remote memory region
1113 using remote DMA writes. On the responder side, incoming bulk DMA
1114 read requests from this peer are permitted and source data from
1115 the configured local memory region. Incoming bulk DMA write
1116 requests are rejected.</li>
1117
1118 </ul>
1119
1120 Consequently, a mirror relationship uses complementary modes:
1121 an initiator operating in mirror-to-local mode communicates with
1122 a responder entry configured as mirror-to-remote, while an
1123 initiator operating in mirror-to-remote mode communicates with a
1124 responder entry configured as mirror-to-local.
1125 ";
1126
1127 sw = rw;
1128 hw = r;
1129 } mode[1:0];
1130
1131 field {
1132 name = {INST_NAME, ".peers.entry[0..NUM_OF_PEERS-1].dma.irq_enable"};
1133 desc = "Enables generation of a PEER_DMA_COMPLETE IRQ event for this peer.
1134 Hardware samples this field together with irq.event_enable.peer_dma_complete
1135 when it accepts the peer DMA request. Changing the field while a transfer is
1136 active does not affect that transfer. Disabling the field does not affect
1137 DMA execution or the done, error, and error_code status fields. For a
1138 failed incoming bulk DMA request, this field is captured when recording
1139 the failure and irq.event_enable.peer_dma_complete is sampled at IRQ
1140 admission. The event identifies this peer by the received source MAC.
1141 Successful incoming requests generate no event. RMEM errors use their
1142 separate irq.event_enable.rmem_error path.";
1143
1144 sw = rw;
1145 hw = r;
1146 } irq_enable[2:2] = 0;
1147
1148 field {
1149 name = {INST_NAME, ".peers.entry[0..NUM_OF_PEERS-1].dma.request[8:8]"};
1150 desc = "Writing one requests a DMA transfer to or from the remote peer,
1151 according to dma.mode. The field remains asserted until the DMA engine
1152 accepts and snapshots the request. Hardware clears it upon acceptance;
1153 while a transfer for this peer is active, a newly asserted request remains
1154 pending. Software or an RTL controller shall read the completion status of
1155 the previous request before asserting this field for the next request and
1156 shall keep the peer configuration stable while this field is asserted.";
1157
1158 sw = rw;
1159 hw = r;
1160 hwclr = true;
1161 } request[8:8] = 0;
1162
1163 field {
1164 name = {INST_NAME, ".peers.entry[0..NUM_OF_PEERS-1].dma.clear_error"};
1165 desc = "Writing one clears this peer's shared RMEM/DMA error flag and error
1166 code. The field remains asserted until hardware accepts and clears the
1167 command. It does not abort an active operation, clear done, or complete
1168 an IRQ claim. A new failure takes precedence over a simultaneous clear.
1169 Starting or successfully completing an operation does not clear a
1170 previously recorded error.";
1171
1172 sw = rw;
1173 hw = r;
1174 hwclr = true;
1175 } clear_error[9:9] = 0;
1176
1177 field {
1178 name = {INST_NAME, ".peers.entry[0..NUM_OF_PEERS-1].dma.idle[16:16]"};
1179 desc = "Indicates whether this peer has no accepted DMA request in progress.
1180 Hardware deasserts this field when a request is accepted and asserts it
1181 after all fragments of the requested block have completed.";
1182
1183 sw = r;
1184 hw = w;
1185 } idle[16:16];
1186
1187 field {
1188 name = {INST_NAME, ".peers.entry[0..NUM_OF_PEERS-1].dma.done[24:24]"};
1189 desc = "Sticky successful-completion flag for this peer. Hardware sets this
1190 field after all fragments of the accepted block transfer complete
1191 successfully and clears it when the next request is accepted.";
1192
1193 sw = r;
1194 hw = w;
1195 } done[24:24];
1196
1197 field {
1198 name = {INST_NAME, ".peers.entry[0..NUM_OF_PEERS-1].dma.error[25:25]"};
1199 desc = "Shared sticky RMEM/DMA error flag for this peer. Hardware sets this
1200 field when a locally initiated RMEM access or bulk DMA transfer fails,
1201 or when servicing an incoming RMEM or bulk DMA request from this peer
1202 fails. Received requests are associated by source MAC. An incoming failure
1203 records its code before exposing its error response, independently of
1204 IRQ enable; it does not change the locally initiated dma.request, idle,
1205 or done state. An incomplete incoming DMA data frame records remote
1206 stream code 10. Multicast response suppression does not suppress this
1207 local error record or an enabled event.
1208 Only dma.clear_error or endpoint reset clears a latched error; starting
1209 or successfully completing another operation does not clear it. The
1210 flag is independent of the IRQ event-enable fields.";
1211
1212 sw = r;
1213 hw = w;
1214 } error[25:25];
1215
1216 field {
1217 name = {INST_NAME, ".peers.entry[0..NUM_OF_PEERS-1].dma.error_code[31:28]"};
1218 desc = "
1219 Shared sticky code for the most recent RMEM or bulk DMA failure for this peer:<ul>
1220 <li>0: No error.</li>
1221 <li>1: Local invalid request, configuration, descriptor, or parameters.</li>
1222 <li>2: Local stream/PDU length or TLAST error.</li>
1223 <li>3: Local supported-size or buffer-capacity overflow.</li>
1224 <li>4: Local AXI read SLVERR response.</li>
1225 <li>5: Local AXI read DECERR response.</li>
1226 <li>6: Local AXI write SLVERR response.</li>
1227 <li>7: Local AXI write DECERR response.</li>
1228 <li>8: Local peer response timeout or Request ID wrap collision. An RMEM access
1229 terminates through its ACK-only boundary; a bulk DMA timeout aborts
1230 the remaining fragments. Hardware does not retry.</li>
1231 <li>9: Remote invalid request, configuration, descriptor, or parameters.</li>
1232 <li>10: Remote stream/PDU length or TLAST error. Also used directly by
1233 the receiver of an incomplete DMA_WRITE_REQ or DMA_READ_RSP,
1234 including missing or incorrect EndOfData.</li>
1235 <li>11: Remote supported-size or buffer-capacity overflow.</li>
1236 <li>12: Remote AXI read SLVERR response.</li>
1237 <li>13: Remote AXI read DECERR response.</li>
1238 <li>14: Remote AXI write SLVERR response.</li>
1239 <li>15: Remote AXI write DECERR response.</li>
1240 </ul>
1241 Codes 1-8 describe errors detected by this endpoint, including
1242 malformed responses, local memory failures, and failures while servicing
1243 received requests. Codes 9-15 describe
1244 failures reported by the responding peer through a valid ERROR_RSP.
1245 Code 10 additionally reports an incomplete incoming DMA data frame
1246 detected at this endpoint, without requiring an ERROR_RSP first.
1247 A missing or incorrect EndOfData uses this same code even when
1248 Ethernet padding masks the short data length. A receiver of an
1249 incomplete unicast DMA_WRITE_REQ records CSR code 10 but sends
1250 ERROR_RSP wire cause 2; multicast writes generate no response.
1251 ERROR_RSP carries a 32-bit cause in the range 1-7, which the initiating
1252 oETP engine validates and maps to CSR code = 8 + wire code. Values
1253 outside 1-7 are invalid response parameters and record local code 1;
1254 they must not be truncated or mistaken for local TIMEOUT = 8.
1255 The oETP initiator completion channel carries this final CSR encoding
1256 for both RMEM and bulk DMA. The responder completion channel reports
1257 its cause 1-7 for serialization as ERROR_RSP; cause 2 on an incomplete
1258 received bulk write corresponds to receiver CSR code 10. Hardware
1259 clears this field only on dma.clear_error or endpoint reset. Successful
1260 operations preserve a recorded failure. A new failure replaces the code
1261 and takes precedence over a simultaneous clear. A failed streaming
1262 transfer may have partially modified memory; error reporting does not
1263 provide rollback or an exact count of modified bytes. Software manages
1264 buffer synchronization and recovery.
1265 ";
1266
1267 sw = r;
1268 hw = w;
1269 } error_code[31:28];
1270 } dma;
1271 } entry[NUM_OF_PEERS];
1272 } peers;
1273
1274 external regfile rmem {
1275 name = {INST_NAME, ".rmem"};
1276 desc = "Virtual memory region for all remote peers, with offsets and sizes defined in the
1277 peers regfile.";
1278
1279 reg word {
1280 name = {INST_NAME, ".rmem.word[0..RMEM_TOTAL_DEPTH-1]"};
1281 desc = "32-bit word in the virtual memory region.";
1282
1283 field {
1284 name = {INST_NAME, ".rmem.word[0..RMEM_TOTAL_DEPTH-1].data[31:0]"};
1285 desc = "Data stored in this virtual memory word.";
1286
1287 sw = rw;
1288 hw = rw;
1289 } data[31:0];
1290 } word[RMEM_TOTAL_DEPTH];
1291 } rmem;
1292};
1293
1294addrmap openenoc_endpoint_interface_top {
1295 name = "openenoc_endpoint_interface_top";
1296 desc = "Control and status address map for an openENOC Endpoint Interface instance.";
1297
1298 littleendian;
1299 default accesswidth = 32;
1300 default regwidth = 32;
1301 default alignment = 4;
1302 addressing = regalign;
1303
1304 openenoc_endpoint_interface #(
1305 .RMEM_TOTAL_DEPTH(1),
1306 .NUM_OF_PEERS(1),
1307 .MAX_RAW_FRAME_SIZE(8192),
1308 .HAS_PEER_DMA(1),
1309 .HAS_NON_OETP_DMA(1),
1310 .HAS_DIRECT_AXIS(1),
1311 .HAS_RMEM(1),
1312 .HAS_IRQ(1),
1313 .INST_NAME("openenoc_endpoint_interface")
1314 ) openenoc_endpoint_interface;
1315};
The openENOC Endpoint Interface CSR memory map and detailed register documentation are derived directly from this SystemRDL specification. The generated CSR documentation provides the corresponding human-readable description of the register hierarchy, address offsets, field layouts, access permissions, reset values, and associated register semantics.
The complete generated CSR documentation is available in openenoc_endpoint_interface_top address map.
Summary
This document defines the HAL architecture and CSR organization for the openENOC Switch and the openENOC Endpoint Interface.
The HAL establishes a consistent software-visible programming model based on memory-mapped Control and Status Registers, while the CSR specification provides the authoritative description of hardware/software interactions. Together, these mechanisms form the foundation for software development, system integration, and verification activities within the openENOC project.