1use bytemuck::bytes_of;
5use num_traits::cast::FromPrimitive;
6
7use std::sync::Arc;
8
9use crate::{
10 arc_msg::ArcMsgOk,
11 chip::{
12 communication::{chip_comms::ChipComms, chip_interface::ChipInterface},
13 hl_comms::HlCommsInterface,
14 },
15 error::{BtWrapper, PlatformError},
16 ArcMsg, ChipImpl,
17};
18
19use super::{
20 eth_addr::EthAddr,
21 hl_comms::HlComms,
22 init::status::{ComponentStatusInfo, InitOptions, WaitStatus},
23 remote::EthAddresses,
24 ArcMsgOptions, AxiData, ChipInitResult, CommsStatus, InitStatus, NeighbouringChip,
25};
26
27pub mod boot_fs;
28pub mod message;
29pub mod spirom_tables;
30
31#[macro_use]
32pub mod telemetry_tags;
33use crate::chip::blackhole::telemetry_tags::TelemetryTags;
34use prost::Message;
35use serde_json::Value;
36use std::collections::HashMap;
37
38fn u32_from_slice(data: &[u8], index: u16) -> u32 {
41 let mut output = 0;
42 let index = index * 4;
43 let data_chunk = &data[index as usize..(index + 4) as usize];
44 for i in data_chunk.iter().rev().copied() {
45 output <<= 8;
46 output |= i as u32;
47 }
48 output
49}
50
51#[derive(Clone)]
52pub struct Blackhole {
53 pub chip_if: Arc<dyn ChipInterface + Send + Sync>,
54 pub arc_if: Arc<dyn ChipComms + Send + Sync>,
55
56 pub message_queue: once_cell::sync::OnceCell<message::MessageQueue<8>>,
57
58 pub eth_locations: [EthCore; 14],
59 pub eth_addrs: EthAddresses,
60
61 spi_buffer_addr: AxiData,
62 telemetry_struct_addr: AxiData,
63 scratch_ram_base: AxiData,
64}
65
66impl HlComms for Blackhole {
67 fn comms_obj(&self) -> (&dyn ChipComms, &dyn ChipInterface) {
68 (self.arc_if.as_ref(), self.chip_if.as_ref())
69 }
70}
71
72impl HlComms for &Blackhole {
73 fn comms_obj(&self) -> (&dyn ChipComms, &dyn ChipInterface) {
74 (self.arc_if.as_ref(), self.chip_if.as_ref())
75 }
76}
77
78#[derive(Clone, Copy, Debug)]
79pub struct EthCore {
80 pub x: u8,
81 pub y: u8,
82 pub enabled: bool,
83}
84
85impl Default for EthCore {
86 fn default() -> Self {
87 Self {
88 x: 0,
89 y: 0,
90 enabled: true,
91 }
92 }
93}
94
95struct SpiBuffer {
96 addr: u32,
97 size: u32,
98}
99
100#[derive(Debug)]
101#[repr(u8)]
102pub enum ArcFwInitStatus {
103 NotStarted = 0,
104 Started = 1,
105 Done = 2,
106 Error = 3,
107 Unknown(u8),
108}
109
110impl From<u8> for ArcFwInitStatus {
111 fn from(value: u8) -> Self {
112 match value {
113 0 => ArcFwInitStatus::NotStarted,
114 1 => ArcFwInitStatus::Started,
115 2 => ArcFwInitStatus::Done,
116 3 => ArcFwInitStatus::Error,
117 other => ArcFwInitStatus::Unknown(other),
118 }
119 }
120}
121
122impl Blackhole {
123 pub(crate) fn init<
124 CC: ChipComms + Send + Sync + 'static,
125 CI: ChipInterface + Send + Sync + 'static,
126 >(
127 arc_if: CC,
128 chip_if: CI,
129 ) -> Result<Self, PlatformError> {
130 let _version = 0x0;
134
135 let output = Blackhole {
136 chip_if: Arc::new(chip_if),
137
138 message_queue: once_cell::sync::OnceCell::new(),
139
140 eth_addrs: EthAddresses::default(),
141
142 spi_buffer_addr: arc_if.axi_translate("arc_ss.reset_unit.SCRATCH_RAM[10]")?,
143 telemetry_struct_addr: arc_if.axi_translate("arc_ss.reset_unit.SCRATCH_RAM[13]")?,
144 scratch_ram_base: arc_if.axi_translate("arc_ss.reset_unit.SCRATCH_RAM[0]")?,
145
146 arc_if: Arc::new(arc_if),
147
148 eth_locations: [
149 EthCore {
150 x: 1,
151 y: 1,
152 ..Default::default()
153 },
154 EthCore {
155 x: 16,
156 y: 1,
157 ..Default::default()
158 },
159 EthCore {
160 x: 2,
161 y: 1,
162 ..Default::default()
163 },
164 EthCore {
165 x: 15,
166 y: 1,
167 ..Default::default()
168 },
169 EthCore {
170 x: 3,
171 y: 1,
172 ..Default::default()
173 },
174 EthCore {
175 x: 14,
176 y: 1,
177 ..Default::default()
178 },
179 EthCore {
180 x: 4,
181 y: 1,
182 ..Default::default()
183 },
184 EthCore {
185 x: 13,
186 y: 1,
187 ..Default::default()
188 },
189 EthCore {
190 x: 5,
191 y: 1,
192 ..Default::default()
193 },
194 EthCore {
195 x: 12,
196 y: 1,
197 ..Default::default()
198 },
199 EthCore {
200 x: 6,
201 y: 1,
202 ..Default::default()
203 },
204 EthCore {
205 x: 11,
206 y: 1,
207 ..Default::default()
208 },
209 EthCore {
210 x: 7,
211 y: 1,
212 ..Default::default()
213 },
214 EthCore {
215 x: 10,
216 y: 1,
217 ..Default::default()
218 },
219 ],
220 };
221
222 Ok(output)
223 }
224
225 pub fn init_eth_addrs(&mut self) -> Result<(), PlatformError> {
226 if self.eth_addrs.masked_version == 0 {
227 let telemetry = self.get_telemetry()?;
228
229 self.eth_addrs = EthAddresses::new(telemetry.eth_fw_version);
230 }
231
232 Ok(())
233 }
234
235 pub fn get_if<T: ChipInterface>(&self) -> Option<&T> {
236 self.chip_if.as_any().downcast_ref::<T>()
237 }
238
239 pub fn arc_fw_init_status(&self) -> Option<ArcFwInitStatus> {
240 self.axi_read32(self.scratch_ram_base.addr + (4 * 2))
241 .ok()
242 .map(|boot_status_0| ArcFwInitStatus::from(((boot_status_0 >> 1) & 0x3) as u8))
243 }
244
245 pub fn check_arc_msg_safe(&self) -> bool {
246 if let Ok(boot_status_0) = self.axi_read32(self.scratch_ram_base.addr + (4 * 2)) {
249 (boot_status_0 & 0x1) == 1
250 } else {
251 false
252 }
253 }
254
255 fn bh_arc_msg(
261 &self,
262 code: u8,
263 data: [u32; 8],
264 timeout: Option<std::time::Duration>,
265 ) -> Result<(u8, u16, [u32; 8]), PlatformError> {
266 if !self.check_arc_msg_safe() {
267 return Err(PlatformError::ArcNotReady(
268 crate::error::ArcReadyError::BootIncomplete,
269 BtWrapper::capture(),
270 ));
271 }
272
273 let mut request = [0; 8];
275 for (src, dst) in data.iter().copied().zip(request.iter_mut()) {
276 *dst = src;
277 }
278 request[0] &= !0xff;
282 request[0] |= u32::from(code);
283
284 let timeout = timeout.unwrap_or(std::time::Duration::from_millis(500));
285
286 let queue = self.message_queue.get_or_try_init::<_, PlatformError>(|| {
287 let message_queue_info_address = self
288 .arc_if
289 .axi_sread32(&self.chip_if, "arc_ss.reset_unit.SCRATCH_RAM[11]")?
290 as u64;
291 let queue_base = self
292 .arc_if
293 .axi_read32(&self.chip_if, message_queue_info_address)?;
294 let queue_sizing = self
295 .arc_if
296 .axi_read32(&self.chip_if, message_queue_info_address + 4)?;
297 let queue_size = queue_sizing & 0xFF;
298 let queue_count = (queue_sizing >> 8) & 0xFF;
299
300 Ok(message::MessageQueue {
301 header_size: 8,
302 entry_size: 8,
303 queue_base: queue_base as u64,
304 queue_size,
305 queue_count,
306 fw_int: self
307 .arc_if
308 .axi_translate("arc_ss.reset_unit.ARC_MISC_CNTL.irq0_trig")?,
309 })
310 })?;
311
312 let response = queue.send_message(self, 2, request, timeout)?;
313 let status = (response[0] & 0xFF) as u8;
314 let rc = (response[0] >> 16) as u16;
315
316 if status < 240 {
317 let data = [
318 response[0],
319 response[1],
320 response[2],
321 response[3],
322 response[4],
323 response[5],
324 response[6],
325 response[7],
326 ];
327 Ok((status, rc, data))
328 } else if status == 0xFF {
329 Err(PlatformError::ArcMsgError(
330 crate::ArcMsgError::ProtocolError {
331 source: crate::ArcMsgProtocolError::MsgNotRecognized(code as u16),
332 backtrace: BtWrapper::capture(),
333 },
334 ))
335 } else {
336 Err(PlatformError::ArcMsgError(
337 crate::ArcMsgError::ProtocolError {
338 source: crate::ArcMsgProtocolError::UnknownErrorCode(status),
339 backtrace: BtWrapper::capture(),
340 },
341 ))
342 }
343 }
344
345 fn get_spi_buffer(&self) -> Result<SpiBuffer, Box<dyn std::error::Error>> {
346 let buffer_addr = self.axi_read32(self.spi_buffer_addr.addr)?;
347
348 Ok(SpiBuffer {
349 addr: (buffer_addr & 0xFFFFFF) + 0x10000000, size: 1 << ((buffer_addr >> 24) & 0xFF),
351 })
352 }
353
354 pub fn spi_write(&self, mut addr: u32, value: &[u8]) -> Result<(), Box<dyn std::error::Error>> {
355 let buffer = self.get_spi_buffer()?;
356
357 let (status, _, _) = self
362 .bh_arc_msg(0xC2, [0, 0, 0, 0, 0, 0, 0, 0], None)
363 .unwrap_or_default();
364
365 if status != 0 {
366 return Err("Failed to unlock spi".into());
367 }
368
369 for chunk in value.chunks(buffer.size as usize) {
370 self.axi_write(buffer.addr as u64, chunk)?;
371 let (status, _, _) = self.bh_arc_msg(
372 0x1A,
373 [0, addr, chunk.len() as u32, buffer.addr, 0, 0, 0, 0],
374 None,
375 )?;
376
377 std::thread::sleep(std::time::Duration::from_millis(100));
378
379 if status != 0 {
380 return Err("Failed to write to SPI".into());
381 }
382
383 addr += chunk.len() as u32;
384 }
385
386 let (status, _, _) = self
388 .bh_arc_msg(0xC3, [0, 0, 0, 0, 0, 0, 0, 0], None)
389 .unwrap_or_default();
390
391 if status != 0 {
392 return Err("Failed to lock spi".into());
393 }
394
395 Ok(())
396 }
397
398 pub fn spi_read(
399 &self,
400 mut addr: u32,
401 value: &mut [u8],
402 ) -> Result<(), Box<dyn std::error::Error>> {
403 let buffer = self.get_spi_buffer()?;
404
405 for chunk in value.chunks_mut(buffer.size as usize) {
406 let (status, _, _) = self.bh_arc_msg(
407 0x19,
408 [0, addr, chunk.len() as u32, buffer.addr, 0, 0, 0, 0],
409 None,
410 )?;
411
412 if status != 0 {
413 return Err("Failed to read from SPI".into());
414 }
415
416 self.axi_read(buffer.addr as u64, chunk)?;
417
418 addr += chunk.len() as u32;
419 }
420
421 Ok(())
422 }
423
424 pub fn get_local_chip_coord(&self) -> Result<EthAddr, PlatformError> {
425 Ok(EthAddr {
426 rack_x: 0,
427 rack_y: 0,
428 shelf_x: 0,
429 shelf_y: 0,
430 })
431 }
432
433 pub fn get_boot_fs_tables_spi_read(
434 &self,
435 tag_name: &str,
436 ) -> Result<Option<(u32, boot_fs::TtBootFsFd)>, Box<dyn std::error::Error>> {
437 let spi_reader = |addr: u32, size: usize| {
438 let mut buf = vec![0; size];
439 self.spi_read(addr, &mut buf).unwrap();
440 buf
441 };
442 Ok(boot_fs::read_tag(spi_reader, tag_name))
443 }
444
445 pub fn decode_boot_fs_table(
446 &self,
447 tag_name: &str,
448 ) -> Result<HashMap<String, Value>, Box<dyn std::error::Error>> {
449 let tag_info = self
453 .get_boot_fs_tables_spi_read(tag_name)?
454 .ok_or_else(|| format!("Tag '{tag_name}' not found in boot FS tables"))?;
455 let spi_addr = tag_info.1.spi_addr;
456 let image_size = tag_info.1.flags.image_size();
457
458 let mut proto_bin = vec![0u8; image_size as usize];
460 self.spi_read(spi_addr, &mut proto_bin)?;
461 let final_decode_map: HashMap<String, Value>;
462 proto_bin = spirom_tables::remove_padding_proto_bin(&proto_bin)?.to_vec();
464
465 if tag_name == "cmfwcfg" || tag_name == "origcfg" {
466 final_decode_map =
467 spirom_tables::to_hash_map(spirom_tables::fw_table::FwTable::decode(&*proto_bin)?);
468 } else if tag_name == "boardcfg" {
469 final_decode_map = spirom_tables::to_hash_map(
470 spirom_tables::read_only::ReadOnly::decode(&*proto_bin)?,
471 );
472 } else if tag_name == "flshinfo" {
473 final_decode_map = spirom_tables::to_hash_map(
474 spirom_tables::flash_info::FlashInfoTable::decode(&*proto_bin)?,
475 );
476 } else {
477 return Err(format!("Unsupported tag name: {tag_name}").into());
478 };
479 Ok(final_decode_map)
480 }
481
482 pub fn encode_and_write_boot_fs_table(
483 &self,
484 hashmap: HashMap<String, Value>,
485 tag_name: &str,
486 ) -> Result<(), Box<dyn std::error::Error>> {
487 let mut proto_bin = if tag_name == "cmfwcfg" {
489 spirom_tables::from_hash_map::<spirom_tables::fw_table::FwTable>(hashmap)
490 .encode_to_vec()
491 } else if tag_name == "boardcfg" {
492 spirom_tables::from_hash_map::<spirom_tables::read_only::ReadOnly>(hashmap)
493 .encode_to_vec()
494 } else if tag_name == "flshinfo" {
495 spirom_tables::from_hash_map::<spirom_tables::flash_info::FlashInfoTable>(hashmap)
496 .encode_to_vec()
497 } else {
498 return Err(format!("Unsupported tag name: {tag_name}").into());
499 };
500 let padding = 4 - (proto_bin.len() % 4);
502 for i in 0..padding {
503 proto_bin.push(i as u8);
504 }
505
506 let tag_info = self
508 .get_boot_fs_tables_spi_read(tag_name)?
509 .ok_or_else(|| format!("Tag '{tag_name}' not found in boot FS tables"))?;
510
511 let mut fd_in_spi = tag_info.1;
512 fd_in_spi.flags.set_image_size(proto_bin.len() as u32);
513
514 let data_chk = spirom_tables::calculate_checksum(&proto_bin);
515 fd_in_spi.data_crc = data_chk;
516 fd_in_spi.fd_crc = 0;
517
518 let fd_chk = {
520 let fd_bytes = bytes_of(&fd_in_spi);
521 spirom_tables::calculate_checksum(&fd_bytes[..fd_bytes.len() - 4])
522 };
523 fd_in_spi.fd_crc = fd_chk;
524
525 self.spi_write(tag_info.0, bytes_of(&fd_in_spi))?;
526 self.spi_write(fd_in_spi.spi_addr, &proto_bin)?;
527
528 Ok(())
529 }
530}
531
532fn default_status() -> InitStatus {
533 InitStatus {
534 comms_status: super::CommsStatus::CanCommunicate,
535 arc_status: ComponentStatusInfo {
536 name: "ARC".to_string(),
537 wait_status: Box::new([WaitStatus::Waiting(None)]),
538
539 start_time: std::time::Instant::now(),
540 timeout: std::time::Duration::from_secs(5),
541 },
542 dram_status: ComponentStatusInfo::init_waiting(
543 "DRAM".to_string(),
544 std::time::Duration::from_secs(300),
545 8,
546 ),
547 eth_status: ComponentStatusInfo::init_waiting(
548 "ETH".to_string(),
549 std::time::Duration::from_secs(15 * 60),
550 14,
551 ),
552 cpu_status: ComponentStatusInfo::init_waiting(
553 "CPU".to_string(),
554 std::time::Duration::from_secs(60),
555 4,
556 ),
557
558 init_options: InitOptions { noc_safe: false },
559
560 unknown_state: false,
561 }
562}
563
564impl ChipImpl for Blackhole {
565 fn update_init_state(
568 &mut self,
569 status: &mut InitStatus,
570 ) -> Result<ChipInitResult, PlatformError> {
571 if status.unknown_state {
572 let init_options = std::mem::take(&mut status.init_options);
573 *status = default_status();
574 status.init_options = init_options;
575 }
576
577 {
578 let comms = &mut status.comms_status;
579 *comms = match self.axi_sread32("arc_ss.reset_unit.SCRATCH_0") {
580 Ok(_) => CommsStatus::CanCommunicate,
581 Err(err) => CommsStatus::CommunicationError(err.to_string()),
582 }
583 }
584
585 {
586 let status = &mut status.arc_status;
587 for s in status.wait_status.iter_mut() {
588 match s {
589 WaitStatus::Waiting(status_string) => {
590 let msg_safe = self.check_arc_msg_safe();
591 let fw_status = self.arc_fw_init_status();
592
593 if let Some(fw_status) = fw_status {
594 match fw_status {
595 ArcFwInitStatus::NotStarted => {
596 *status_string = Some("BH FW boot not started".to_string());
597 }
598 ArcFwInitStatus::Started => {
599 *status_string = Some("BH FW boot not complete".to_string());
600 }
601 ArcFwInitStatus::Done => {
602 if !msg_safe {
603 *status_string = Some(
604 "BH FW arc msg queue init not complete".to_string(),
605 );
606 } else {
607 *s = WaitStatus::JustFinished;
608 }
609 }
610 ArcFwInitStatus::Error => {
611 *status_string = Some("BH FW Boot error".to_string());
612 *s = WaitStatus::Error(
613 super::init::status::ArcInitError::WaitingForInit(
614 crate::error::ArcReadyError::BootError,
615 ),
616 );
617 }
618 ArcFwInitStatus::Unknown(status) => {
619 *status_string = Some(format!("BH FW Boot status unknown {status} (will wait to see if it becomes known)"));
620 }
621 }
622
623 if let WaitStatus::Waiting(_) = s {
625 if status.start_time.elapsed() > status.timeout {
627 *s = WaitStatus::Error(
628 super::init::status::ArcInitError::WaitingForInit(
629 crate::error::ArcReadyError::BootIncomplete,
630 ),
631 );
632 }
633 }
634 } else {
635 *status_string =
636 Some("Failed to access fw to read init status".to_string());
637 *s = WaitStatus::Error(
638 super::init::status::ArcInitError::WaitingForInit(
639 crate::error::ArcReadyError::NoAccess,
640 ),
641 );
642 }
643 }
644 WaitStatus::JustFinished => {
645 *s = WaitStatus::Done;
646 }
647 _ => {}
648 }
649 }
650 }
651
652 {
653 let status = &mut status.dram_status;
654 for s in status.wait_status.iter_mut() {
655 *s = WaitStatus::Done;
656 }
657 }
658
659 {
660 let status = &mut status.eth_status;
661 for s in status.wait_status.iter_mut() {
662 *s = WaitStatus::Done;
663 }
664 }
665
666 {
667 let status = &mut status.cpu_status;
668 for s in status.wait_status.iter_mut() {
669 *s = WaitStatus::Done;
670 }
671 }
672
673 Ok(ChipInitResult::NoError)
674 }
675
676 fn get_arch(&self) -> luwen_def::Arch {
677 luwen_def::Arch::Blackhole
678 }
679
680 fn arc_msg(&self, msg: ArcMsgOptions) -> Result<ArcMsgOk, PlatformError> {
681 let code = msg.msg.msg_code();
682 let data = if let ArcMsg::Buf(msg) = msg.msg {
683 msg
684 } else {
685 let args = msg.msg.args();
686 [0, args.0 as u32 | ((args.1 as u32) << 16), 0, 0, 0, 0, 0, 0]
687 };
688
689 let (_status, rc, response) = self.bh_arc_msg(code as u8, data, Some(msg.timeout))?;
690 Ok(match msg.msg {
691 ArcMsg::Buf(_) => ArcMsgOk::OkBuf(response),
692 _ => ArcMsgOk::Ok {
693 rc: rc as u32,
694 arg: response[1],
695 },
696 })
697 }
698
699 fn get_neighbouring_chips(&self) -> Result<Vec<NeighbouringChip>, crate::error::PlatformError> {
700 Ok(vec![])
701 }
702
703 fn as_any(&self) -> &dyn std::any::Any {
704 self
705 }
706
707 fn get_telemetry(&self) -> Result<super::Telemetry, PlatformError> {
708 let mut scratch_reg_13_value = [0u8; 4];
714 self.axi_read_field(&self.telemetry_struct_addr, &mut scratch_reg_13_value)?;
715 let telem_struct_addr = u32::from_le_bytes(scratch_reg_13_value);
716 if telem_struct_addr == 0 {
717 return Err(PlatformError::ArcNotReady(
718 crate::error::ArcReadyError::BootIncomplete,
719 BtWrapper::capture(),
720 ));
721 }
722 if !(0x10000000..=0x1007FFFF).contains(&telem_struct_addr) {
724 return Err(PlatformError::Generic(
725 format!("Invalid Telemetry struct address: 0x{telem_struct_addr:08x}"),
726 BtWrapper::capture(),
727 ));
728 }
729
730 let _version = self.axi_read32(telem_struct_addr as u64)?;
733 let entry_count = self.axi_read32(telem_struct_addr as u64 + 4)?;
734
735 let mut telemetry_tags_data_block: Vec<u8> = vec![0u8; (entry_count + 1) as usize * 4];
741 let mut telem_data_block: Vec<u8> = vec![0u8; (entry_count + 1) as usize * 4];
742
743 self.axi_read(
744 (telem_struct_addr + 8) as u64,
745 &mut telemetry_tags_data_block,
746 )?;
747 self.axi_read(
748 (telem_struct_addr + 8 + entry_count * 4) as u64,
749 &mut telem_data_block,
750 )?;
751
752 let mut telemetry_data = super::Telemetry::default();
754 for i in 0..entry_count as u16 {
755 let entry = u32_from_slice(&telemetry_tags_data_block, i);
756 let tag = entry & 0xFFFF;
757 let offset = (entry >> 16) & 0xFFFF;
758 let data = u32_from_slice(&telem_data_block, offset as u16);
759 if let Some(tag) = TelemetryTags::from_u32(tag) {
761 match tag {
762 TelemetryTags::BoardIdHigh => telemetry_data.board_id_high = data,
763 TelemetryTags::BoardIdLow => telemetry_data.board_id_low = data,
764 TelemetryTags::AsicId => telemetry_data.asic_id = data,
765 TelemetryTags::HarvestingState => telemetry_data.harvesting_state = data,
766 TelemetryTags::UpdateTelemSpeed => telemetry_data.update_telem_speed = data,
767 TelemetryTags::Vcore => telemetry_data.vcore = data,
768 TelemetryTags::Tdp => telemetry_data.tdp = data,
769 TelemetryTags::Tdc => telemetry_data.tdc = data,
770 TelemetryTags::VddLimits => telemetry_data.vdd_limits = data,
771 TelemetryTags::ThmLimits => telemetry_data.thm_limits = data,
772 TelemetryTags::AsicTemperature => telemetry_data.asic_temperature = data,
773 TelemetryTags::VregTemperature => telemetry_data.vreg_temperature = data,
774 TelemetryTags::BoardTemperature => telemetry_data.board_temperature = data,
775 TelemetryTags::AiClk => telemetry_data.aiclk = data,
776 TelemetryTags::AxiClk => telemetry_data.axiclk = data,
777 TelemetryTags::ArcClk => telemetry_data.arcclk = data,
778 TelemetryTags::L2CPUClk0 => telemetry_data.l2cpuclk0 = data,
779 TelemetryTags::L2CPUClk1 => telemetry_data.l2cpuclk1 = data,
780 TelemetryTags::L2CPUClk2 => telemetry_data.l2cpuclk2 = data,
781 TelemetryTags::L2CPUClk3 => telemetry_data.l2cpuclk3 = data,
782 TelemetryTags::EthLiveStatus => telemetry_data.eth_status0 = data,
783 TelemetryTags::DdrStatus => telemetry_data.ddr_status = data,
784 TelemetryTags::DdrSpeed => telemetry_data.ddr_speed = Some(data),
785 TelemetryTags::EthFwVersion => telemetry_data.eth_fw_version = data,
786 TelemetryTags::DdrFwVersion => telemetry_data.ddr_fw_version = data,
787 TelemetryTags::BmAppFwVersion => telemetry_data.m3_app_fw_version = data,
788 TelemetryTags::BmBlFwVersion => telemetry_data.m3_bl_fw_version = data,
789 TelemetryTags::FlashBundleVersion => telemetry_data.fw_bundle_version = data,
790 TelemetryTags::L2cpuFwVersion => telemetry_data.l2cpu_fw_version = data,
792 TelemetryTags::FanSpeed => telemetry_data.fan_speed = data,
793 TelemetryTags::TimerHeartbeat => {
794 telemetry_data.timer_heartbeat = data;
795 }
796 TelemetryTags::TelemEnumCount => telemetry_data.entry_count = data,
797 TelemetryTags::EnabledTensixCol => telemetry_data.tensix_enabled_col = data,
798 TelemetryTags::EnabledEth => telemetry_data.enabled_eth = data,
799 TelemetryTags::EnabledGddr => telemetry_data.enabled_gddr = data,
800 TelemetryTags::EnabledL2Cpu => telemetry_data.enabled_l2cpu = data,
801 TelemetryTags::PcieUsage => telemetry_data.enabled_pcie = data,
802 TelemetryTags::NocTranslation => {
803 telemetry_data.noc_translation_enabled = data != 0
804 }
805 TelemetryTags::FanRpm => telemetry_data.fan_rpm = data,
806 TelemetryTags::Gddr01Temp => telemetry_data.gddr01_temp = data,
807 TelemetryTags::Gddr23Temp => telemetry_data.gddr23_temp = data,
808 TelemetryTags::Gddr45Temp => telemetry_data.gddr45_temp = data,
809 TelemetryTags::Gddr67Temp => telemetry_data.gddr67_temp = data,
810 TelemetryTags::Gddr01CorrErrs => telemetry_data.gddr01_corr_errs = data,
811 TelemetryTags::Gddr23CorrErrs => telemetry_data.gddr23_corr_errs = data,
812 TelemetryTags::Gddr45CorrErrs => telemetry_data.gddr45_corr_errs = data,
813 TelemetryTags::Gddr67CorrErrs => telemetry_data.gddr67_corr_errs = data,
814 TelemetryTags::GddrUncorrErrs => telemetry_data.gddr_uncorr_errs = data,
815 TelemetryTags::MaxGddrTemp => telemetry_data.max_gddr_temp = data,
816 TelemetryTags::AsicLocation => telemetry_data.asic_location = data,
817 TelemetryTags::BoardPowerLimit => telemetry_data.board_power_limit = data,
818 TelemetryTags::InputPower => telemetry_data.input_power = data,
819 TelemetryTags::TdcLimitMax => telemetry_data.tdc_limit_max = data,
820 TelemetryTags::ThmLimitThrottle => telemetry_data.thm_limit_throttle = data,
821 TelemetryTags::ThermTripCount => telemetry_data.therm_trip_count = data,
822 TelemetryTags::AsicIdHigh => telemetry_data.asic_id_high = data,
823 TelemetryTags::AsicIdLow => telemetry_data.asic_id_low = data,
824 TelemetryTags::AiclkLimitMax => telemetry_data.aiclk_limit_max = data,
825 TelemetryTags::TdpLimitMax => telemetry_data.tdp_limit_max = data,
826 _ => (),
827 }
828 }
829 }
830 telemetry_data.board_id =
831 ((telemetry_data.board_id_high as u64) << 32) | telemetry_data.board_id_low as u64;
832 telemetry_data.arch = self.get_arch();
833 Ok(telemetry_data)
834 }
835
836 fn get_device_info(&self) -> Result<Option<crate::DeviceInfo>, PlatformError> {
837 Ok(self.chip_if.get_device_info()?)
838 }
839}