u280_shell_rhdl/
writer.rs1use rhdl::prelude::*;
4
5use crate::axi::AXI_RESP_OKAY;
6
7#[derive(Clone, Copy, Debug, Default, Digital, Eq, PartialEq)]
9pub enum WriterState {
10 #[default]
12 Idle,
13 Address,
15 Data,
17 Response,
19}
20
21#[derive(Clone, Copy, Debug, Default, Digital, Eq, PartialEq)]
23pub struct FrameQueue {
24 pub count: b2,
26 pub head_slot: b1,
28 pub head_job: b32,
30 pub tail_slot: b1,
32 pub tail_job: b32,
34}
35
36#[derive(Clone, Copy, Debug, Default, Digital, Eq, PartialEq)]
38pub struct FrameQueueOperation {
39 pub dequeue: bool,
41 pub enqueue: bool,
43 pub slot: b1,
45 pub job: b32,
47}
48
49#[derive(Clone, Copy, Debug, Default, Digital, Eq, PartialEq)]
51pub struct FrameQueueUpdate {
52 pub queue: FrameQueue,
54 pub fatal: bool,
56}
57
58#[kernel]
60pub fn frame_queue_update_kernel(
61 current: FrameQueue,
62 operation: FrameQueueOperation,
63) -> FrameQueueUpdate {
64 let mut next = current;
65 let mut fatal = current.count > b2(2);
66 if operation.dequeue && operation.enqueue {
67 if current.count == b2(1) {
68 next.count = b2(1);
69 next.head_slot = operation.slot;
70 next.head_job = operation.job;
71 } else if current.count == b2(2) {
72 next.count = b2(2);
73 next.head_slot = current.tail_slot;
74 next.head_job = current.tail_job;
75 next.tail_slot = operation.slot;
76 next.tail_job = operation.job;
77 } else {
78 fatal = true;
79 }
80 } else if operation.dequeue {
81 if current.count == b2(1) {
82 next.count = b2(0);
83 } else if current.count == b2(2) {
84 next.count = b2(1);
85 next.head_slot = current.tail_slot;
86 next.head_job = current.tail_job;
87 } else {
88 fatal = true;
89 }
90 } else if operation.enqueue {
91 if current.count == b2(0) {
92 next.count = b2(1);
93 next.head_slot = operation.slot;
94 next.head_job = operation.job;
95 } else if current.count == b2(1) {
96 next.count = b2(2);
97 next.tail_slot = operation.slot;
98 next.tail_job = operation.job;
99 } else {
100 fatal = true;
101 }
102 }
103 FrameQueueUpdate { queue: next, fatal }
104}
105
106#[kernel]
108pub fn output_job_address_kernel(base: b64, job_id: b32) -> b64 {
109 let wide_job: b64 = job_id.resize();
110 base + (wide_job << 12)
111}
112
113#[kernel]
115pub fn output_response_is_canonical_kernel(bid: b1, bresp: b2) -> bool {
116 bid == b1(0) && bresp == AXI_RESP_OKAY
117}
118
119#[kernel]
121pub fn frame_slot_is_reserved_kernel(
122 queue: FrameQueue,
123 capture_active: bool,
124 capture_slot: b1,
125 candidate: b1,
126) -> bool {
127 let capture_match = capture_active && capture_slot == candidate;
128 let head_match = queue.count != b2(0) && queue.head_slot == candidate;
129 let tail_match = queue.count == b2(2) && queue.tail_slot == candidate;
130 capture_match || head_match || tail_match
131}
132
133#[derive(Clone, Copy, Debug, Default, Digital, Eq, PartialEq)]
135pub struct MemoryCompletionTiming {
136 pub seen: bool,
138 pub first: b64,
140 pub last: b64,
142 pub span: b64,
144}
145
146#[kernel]
148pub fn record_memory_completion_kernel(
149 current: MemoryCompletionTiming,
150 cycle: b64,
151 canonical_payload_b: bool,
152) -> MemoryCompletionTiming {
153 let mut next = current;
154 if canonical_payload_b {
155 if current.seen {
156 next.last = cycle;
157 next.span = cycle - current.first;
158 } else {
159 next.seen = true;
160 next.first = cycle;
161 next.last = cycle;
162 next.span = b64(0);
163 }
164 }
165 next
166}