Dawn Framework 1.0
Universal data acquisition framework for embedded systems
inspect.cxx
1// dawn/src/proto/shell/inspect.cxx
2//
3// SPDX-License-Identifier: Apache-2.0
4//
5
6#include "dawn/proto/shell/pretty.hxx"
7
8#ifdef CONFIG_DAWN_PROTO_SHELL_INSPECT
9
10# include <cstdlib>
11# include <cstring>
12
13# include "dawn/common/object.hxx"
14# include "dawn/common/objectid.hxx"
15# include "dawn/dev/inspector.hxx"
16# include "dawn/io/common.hxx"
17# include "dawn/io/config.hxx"
18
19using namespace dawn;
20
21# define DAWN_PROTO_SHELL_LIST_ARG_MAX 64
22
23void CProtoShellPretty::cmdList(const char *arg)
24{
25 CDevInspector *inspector;
26 size_t count;
27 size_t i;
28 const CIOCommon *io;
29 const CObject *obj;
30 bool verbose;
31 bool show_io;
32 bool show_prog;
33 bool show_proto;
34
35 verbose = false;
36 show_io = true;
37 show_prog = true;
38 show_proto = true;
39
40 if (arg != nullptr && arg[0] != '\0')
41 {
42 char argbuf[DAWN_PROTO_SHELL_LIST_ARG_MAX];
43 char *saveptr = nullptr;
44 char *token;
45 bool filtered = false;
46
47 std::strncpy(argbuf, arg, sizeof(argbuf) - 1);
48 argbuf[sizeof(argbuf) - 1] = '\0';
49
50 token = strtok_r(argbuf, " \t", &saveptr);
51 while (token != nullptr)
52 {
53 if (std::strcmp(token, "verbose") == 0 || std::strcmp(token, "full") == 0)
54 {
55 verbose = true;
56 }
57 else if (std::strcmp(token, "io") == 0)
58 {
59 if (!filtered)
60 {
61 show_io = false;
62 show_prog = false;
63 show_proto = false;
64 filtered = true;
65 }
66 show_io = true;
67 }
68 else if (std::strcmp(token, "prog") == 0)
69 {
70 if (!filtered)
71 {
72 show_io = false;
73 show_prog = false;
74 show_proto = false;
75 filtered = true;
76 }
77 show_prog = true;
78 }
79 else if (std::strcmp(token, "proto") == 0)
80 {
81 if (!filtered)
82 {
83 show_io = false;
84 show_prog = false;
85 show_proto = false;
86 filtered = true;
87 }
88 show_proto = true;
89 }
90 else
91 {
92 fprintf(outstream, "Usage: list [io|prog|proto] [verbose]\n");
93 return;
94 }
95
96 token = strtok_r(nullptr, " \t", &saveptr);
97 }
98 }
99
100 inspector = CDevInspector::getInst();
101
102 fprintf(outstream, "\n");
103 fprintf(outstream, "Object Inventory\n");
104 fprintf(outstream, "================\n\n");
105
106 // List IO objects
107
108 if (show_io)
109 {
110 count = inspector->getIOCount();
111 fprintf(outstream, "IOs: %zu objects\n", count);
112
113 if (count > 0)
114 {
115# ifdef CONFIG_DAWN_IO_HAS_STATS
116 if (verbose)
117 {
118 fprintf(outstream,
119 " Name ObjID Type Cls DType Dim Size Flags "
120 "Stats (R/W/E)\n");
121 fprintf(outstream,
122 " -------------- ---------- ---- ---- ------ --- ---- ------ "
123 "--------------\n");
124 }
125 else
126 {
127 fprintf(outstream, " Name ObjID DType[Dim] Cls Flags R/W/E\n");
128 fprintf(outstream, " -------------- ---------- ----------- --- ------ -------\n");
129 }
130# else
131 if (verbose)
132 {
133 fprintf(outstream, " Name ObjID Type Cls DType Dim Size Flags\n");
134 fprintf(outstream, " -------------- ---------- ---- ---- ------ --- ---- ------\n");
135 }
136 else
137 {
138 fprintf(outstream, " Name ObjID DType[Dim] Cls Flags\n");
139 fprintf(outstream, " -------------- ---------- ----------- --- ------\n");
140 }
141# endif
142
143 for (i = 0; i < count; i++)
144 {
145 io = inspector->getIO(i);
146 if (io == nullptr)
147 {
148 continue;
149 }
150
151 if (verbose)
152 {
153 fprintf(outstream, " %-14s ", io->getName());
154 fprintf(outstream, "0x%08" PRIx32 " ", io->getIdV());
155 fprintf(outstream,
156 "%4d %4d %-6s ",
157 io->getType(),
158 io->getCls(),
159 SObjectId::dtypeToString(io->getDtype()));
160 fprintf(outstream, "%3zu %4zu ", io->getDataDim(), io->getDataSize());
161 }
162 else
163 {
164 fprintf(outstream,
165 " %-14s 0x%08" PRIx32 " %s[%zu] %3d ",
166 io->getName(),
167 io->getIdV(),
168 SObjectId::dtypeToString(io->getDtype()),
169 io->getDataDim(),
170 io->getCls());
171 }
172
173 fprintf(outstream,
174 "%c%c%c%c%c",
175 io->isRead() ? 'R' : '-',
176 io->isWrite() ? 'W' : '-',
177 io->isNotify() ? 'N' : '-',
178 io->isTimestamp() ? 'T' : '-',
179 io->getCfgFlag() ? 'C' : '-');
180
181# ifdef CONFIG_DAWN_IO_HAS_STATS
182 const auto &stats = io->getStats();
183 if (verbose)
184 {
185 fprintf(outstream,
186 " %6" PRIu32 "/%6" PRIu32 "/%6" PRIu32 "\n",
187 stats.read_count,
188 stats.write_count,
189 stats.error_count);
190 }
191 else
192 {
193 fprintf(outstream,
194 " %" PRIu32 "/%" PRIu32 "/%" PRIu32 "\n",
195 stats.read_count,
196 stats.write_count,
197 stats.error_count);
198 }
199# else
200 fprintf(outstream, "\n");
201# endif
202 }
203 }
204
205 fprintf(outstream, "\n");
206 }
207
208 // List PROG objects
209
210 if (show_prog)
211 {
212 count = inspector->getProgCount();
213 fprintf(outstream, "PROGs: %zu objects\n", count);
214
215 if (count > 0)
216 {
217 if (verbose)
218 {
219 fprintf(outstream, " Name ObjID Type Cls Running\n");
220 fprintf(outstream, " -------------- ---------- ---- ---- -------\n");
221 }
222 else
223 {
224 fprintf(outstream, " Name ObjID Cls State\n");
225 fprintf(outstream, " -------------- ---------- --- -------\n");
226 }
227
228 for (i = 0; i < count; i++)
229 {
230 obj = inspector->getProg(i);
231 if (obj == nullptr)
232 {
233 continue;
234 }
235
236 if (verbose)
237 {
238 fprintf(outstream, " %-14s ", obj->getName());
239 fprintf(outstream, "0x%08" PRIx32 " ", obj->getIdV());
240 fprintf(outstream,
241 "%4d %4d %7s\n",
242 obj->getType(),
243 obj->getCls(),
244 obj->getState() == CObject::STATE_RUNNING ? "YES" : "NO");
245 }
246 else
247 {
248 fprintf(outstream,
249 " %-14s 0x%08" PRIx32 " %3d %s\n",
250 obj->getName(),
251 obj->getIdV(),
252 obj->getCls(),
253 obj->getState() == CObject::STATE_RUNNING ? "RUNNING" : "STOPPED");
254 }
255 }
256 }
257
258 fprintf(outstream, "\n");
259 }
260
261 // List PROTO objects
262
263 if (show_proto)
264 {
265 count = inspector->getProtoCount();
266 fprintf(outstream, "PROTOs: %zu objects\n", count);
267
268 if (count > 0)
269 {
270 if (verbose)
271 {
272 fprintf(outstream, " Name ObjID Type Cls Running\n");
273 fprintf(outstream, " -------------- ---------- ---- ---- -------\n");
274 }
275 else
276 {
277 fprintf(outstream, " Name ObjID Cls State\n");
278 fprintf(outstream, " -------------- ---------- --- -------\n");
279 }
280
281 for (i = 0; i < count; i++)
282 {
283 obj = inspector->getProto(i);
284 if (obj == nullptr)
285 {
286 continue;
287 }
288
289 if (verbose)
290 {
291 fprintf(outstream, " %-14s ", obj->getName());
292 fprintf(outstream, "0x%08" PRIx32 " ", obj->getIdV());
293 fprintf(outstream,
294 "%4d %4d %7s\n",
295 obj->getType(),
296 obj->getCls(),
297 obj->getState() == CObject::STATE_RUNNING ? "YES" : "NO");
298 }
299 else
300 {
301 fprintf(outstream,
302 " %-14s 0x%08" PRIx32 " %3d %s\n",
303 obj->getName(),
304 obj->getIdV(),
305 obj->getCls(),
306 obj->getState() == CObject::STATE_RUNNING ? "RUNNING" : "STOPPED");
307 }
308 }
309 }
310
311 fprintf(outstream, "\n");
312 }
313
314 fprintf(outstream, "Flags: R=Read W=Write N=Notify T=Timestamp C=Config\n");
315# ifdef CONFIG_DAWN_IO_HAS_STATS
316 fprintf(outstream, "Stats: R=Reads W=Writes E=Errors\n");
317# endif
318 fprintf(outstream, "Use 'list io|prog|proto' to filter and 'list verbose' for details.\n");
319 fprintf(outstream, "\n");
320}
321
322void CProtoShellPretty::cmdInspect(const char *arg)
323{
324 char *endptr;
325 uint32_t objid_val;
326 CDevInspector *inspector;
327 const CObject *obj;
328 const char *handler_type;
329
330 if (!arg || arg[0] == '\0')
331 {
332 fprintf(outstream, "Usage: inspect <object_id>\n");
333 fprintf(outstream, " object_id: hex (0xNNNNNNNN) or decimal\n");
334 return;
335 }
336
337 // Parse object ID
338
339 objid_val = strtoul(arg, &endptr, 0);
340 if (*endptr != '\0' && *endptr != ' ' && *endptr != '\t')
341 {
342 fprintf(outstream, "Error: invalid object ID '%s'\n", arg);
343 return;
344 }
345
346 // Find object
347
348 inspector = CDevInspector::getInst();
349 obj = inspector->findObject(objid_val);
350
351 if (!obj)
352 {
353 fprintf(outstream, "Error: object 0x%08" PRIx32 " not found\n", objid_val);
354 return;
355 }
356
357 // Determine handler type
358
359 switch (obj->getType())
360 {
361 case SObjectId::OBJTYPE_IO:
362 handler_type = "IO";
363 break;
364 case SObjectId::OBJTYPE_PROG:
365 handler_type = "PROG";
366 break;
367 case SObjectId::OBJTYPE_PROTO:
368 handler_type = "PROTO";
369 break;
370 default:
371 handler_type = "UNKNOWN";
372 break;
373 }
374
375 // Display detailed information
376
377 fprintf(outstream, "\n");
378 fprintf(outstream, "Object Details\n");
379 fprintf(outstream, "==============\n\n");
380 fprintf(outstream, " Name: %s\n", obj->getName());
381 fprintf(outstream, " Object ID: 0x%08" PRIx32 "\n", obj->getIdV());
382 fprintf(outstream, " Handler: %s\n", handler_type);
383 fprintf(outstream, "\n");
384
385 // Object ID breakdown
386
387 fprintf(outstream, " Type: 0x%02x ", obj->getType());
388 switch (obj->getType())
389 {
390 case SObjectId::OBJTYPE_IO:
391 fprintf(outstream, "(IO)\n");
392 break;
393 case SObjectId::OBJTYPE_PROG:
394 fprintf(outstream, "(PROG)\n");
395 break;
396 case SObjectId::OBJTYPE_PROTO:
397 fprintf(outstream, "(PROTO)\n");
398 break;
399 default:
400 fprintf(outstream, "(UNKNOWN)\n");
401 break;
402 }
403
404 fprintf(outstream, " Class: 0x%03x (%u)\n", obj->getCls(), obj->getCls());
405 fprintf(outstream, " Data Type: 0x%02x ", obj->getDtype());
406
407 // Display data type name
408
409 if (obj->getDtype() == SObjectId::DTYPE_ANY)
410 {
411 fprintf(outstream, "(%s)\n", SObjectId::dtypeToString(obj->getDtype()));
412 }
413 else if (obj->getDtype() == SObjectId::DTYPE_BLOCK)
414 {
415 fprintf(outstream, "(%s)\n", SObjectId::dtypeToString(obj->getDtype()));
416 }
417 else
418 {
419 fprintf(outstream,
420 "(%s, %zu bytes)\n",
421 SObjectId::dtypeToString(obj->getDtype()),
422 obj->getDtypeSize());
423 }
424
425 if (obj->getType() == SObjectId::OBJTYPE_IO)
426 {
427 const CIOCommon *io = static_cast<const CIOCommon *>(obj);
428 fprintf(outstream,
429 " Dimension: %zu (item size %zu bytes)\n",
430 io->getDataDim(),
431 io->getDataSize());
432 }
433
434 fprintf(outstream, " Flags: 0x%02x\n", obj->getFlags());
435 fprintf(outstream, " Instance: %u\n", obj->getPriv());
436 fprintf(outstream, "\n");
437
438 // Configuration info
439
440 if (obj->getCfgFlag())
441 {
442 fprintf(outstream, " Config: Yes\n");
443 }
444 else
445 {
446 fprintf(outstream, " Config: No\n");
447 }
448
449 fprintf(outstream, "\n");
450
451 // ConfigIO binding information (only for ConfigIO objects)
452
453 if (obj->getType() == SObjectId::OBJTYPE_IO && obj->getCls() == CIOCommon::IO_CLASS_CONFIG)
454 {
455 const CIOConfig *cfg_io = static_cast<const CIOConfig *>(obj);
456
457 fprintf(outstream, "ConfigIO Bindings\n");
458 fprintf(outstream, "-----------------\n");
459
460 if (cfg_io->map.empty())
461 {
462 fprintf(outstream, " (no bindings)\n");
463 }
464 else
465 {
466 for (const auto &[id, bound_obj] : cfg_io->map)
467 {
468 if (bound_obj)
469 {
470 const char *type_str = "UNKNOWN";
471
472 switch (bound_obj->getType())
473 {
474 case SObjectId::OBJTYPE_IO:
475 type_str = "IO";
476 break;
477 case SObjectId::OBJTYPE_PROG:
478 type_str = "PROG";
479 break;
480 case SObjectId::OBJTYPE_PROTO:
481 type_str = "PROTO";
482 break;
483 }
484
485 fprintf(outstream,
486 " -> %s: %s (0x%08" PRIx32 ")\n",
487 type_str,
488 bound_obj->getName(),
489 bound_obj->getIdV());
490 }
491 else
492 {
493 fprintf(outstream, " -> 0x%08" PRIx32 " (not bound yet)\n", id);
494 }
495 }
496 }
497
498 fprintf(outstream, "\n");
499 }
500
501 // Runtime statistics (only for IO objects)
502
503# ifdef CONFIG_DAWN_IO_HAS_STATS
504 if (obj->getType() == SObjectId::OBJTYPE_IO)
505 {
506 const CIOCommon *io = static_cast<const CIOCommon *>(obj);
507 const CIOCommon::IOStats &stats = io->getStats();
508 fprintf(outstream, "Statistics\n");
509 fprintf(outstream, "----------\n");
510 fprintf(outstream, " Reads: %" PRIu32 "\n", stats.read_count);
511 fprintf(outstream, " Writes: %" PRIu32 "\n", stats.write_count);
512 fprintf(outstream, " Errors: %" PRIu32 "\n", stats.error_count);
513 fprintf(outstream, "\n");
514 }
515# endif
516}
517
518void CProtoShellPretty::cmdTree(const char *arg)
519{
520 CDevInspector *inspector;
521 size_t proto_count;
522 size_t prog_count;
523 size_t io_count;
524 size_t i;
525 size_t j;
526 size_t k;
527 const CObject *proto;
528 const CObject *prog;
529 const CIOCommon *io;
530 const CObject *bound_objs[128];
531 size_t binding_count;
532 const CIOCommon *io_bindings[128];
533 size_t io_binding_count;
534 bool is_bound;
535 bool has_unbound;
536 const CObject *bound_obj;
537
538 (void)arg;
539
540 inspector = CDevInspector::getInst();
541
542 fprintf(outstream, "\n");
543 fprintf(outstream, "Data Flow Tree\n");
544 fprintf(outstream, "==============\n\n");
545
546 // Show PROTO objects at top level (communication endpoints)
547
548 proto_count = inspector->getProtoCount();
549
550 if (proto_count == 0)
551 {
552 fprintf(outstream, "(no protocol objects)\n\n");
553 }
554 else
555 {
556 for (i = 0; i < proto_count; i++)
557 {
558 proto = inspector->getProto(i);
559 if (proto == nullptr)
560 {
561 continue;
562 }
563
564 fprintf(outstream, "PROTO: %s\n", proto->getName());
565
566 binding_count = inspector->getProtoBindings(i, bound_objs, 128);
567
568 if (binding_count > 0)
569 {
570 for (j = 0; j < binding_count; j++)
571 {
572 const bool is_last = (j == binding_count - 1);
573 const char *branch = is_last ? "└──" : "├──";
574 const char *cont = is_last ? " " : "│ ";
575
576 bound_obj = bound_objs[j];
577
578 // Check if this is a PROG or IO object
579
580 if (bound_obj->getType() == SObjectId::OBJTYPE_PROG)
581 {
582 fprintf(outstream, "%s PROG: %s\n", branch, bound_obj->getName());
583
584 // Show PROG's bound IO objects - find prog index
585
586 for (k = 0; k < inspector->getProgCount(); k++)
587 {
588 if (inspector->getProg(k)->getIdV() == bound_obj->getIdV())
589 {
590 io_binding_count = inspector->getProgIOBindings(k, io_bindings, 128);
591
592 if (io_binding_count > 0)
593 {
594 size_t io_idx;
595
596 for (io_idx = 0; io_idx < io_binding_count; io_idx++)
597 {
598 const bool io_last = (io_idx == io_binding_count - 1);
599 const char *io_branch = io_last ? "└──" : "├──";
600
601 fprintf(outstream,
602 "%s %s IO: %s\n",
603 cont,
604 io_branch,
605 io_bindings[io_idx]->getName());
606 }
607 }
608
609 break;
610 }
611 }
612 }
613 else if (bound_obj->getType() == SObjectId::OBJTYPE_IO)
614 {
615 fprintf(outstream, "%s IO: %s\n", branch, bound_obj->getName());
616 }
617 }
618 }
619 else
620 {
621 fprintf(outstream, " (no bindings)\n");
622 }
623
624 fprintf(outstream, "\n");
625 }
626 }
627
628 // Show unbound PROG objects
629
630 prog_count = inspector->getProgCount();
631 has_unbound = false;
632
633 for (i = 0; i < prog_count; i++)
634 {
635 prog = inspector->getProg(i);
636 if (prog == nullptr)
637 {
638 continue;
639 }
640
641 is_bound = false;
642
643 // Check if this PROG is bound to any PROTO
644
645 for (j = 0; j < proto_count; j++)
646 {
647 binding_count = inspector->getProtoBindings(j, bound_objs, 128);
648
649 for (k = 0; k < binding_count; k++)
650 {
651 if (bound_objs[k]->getIdV() == prog->getIdV())
652 {
653 is_bound = true;
654 break;
655 }
656 }
657
658 if (is_bound)
659 {
660 break;
661 }
662 }
663
664 if (!is_bound)
665 {
666 if (!has_unbound)
667 {
668 fprintf(outstream, "Unbound PROG objects:\n");
669 has_unbound = true;
670 }
671
672 fprintf(outstream, " * %s\n", prog->getName());
673
674 io_binding_count = inspector->getProgIOBindings(i, io_bindings, 128);
675
676 if (io_binding_count > 0)
677 {
678 fprintf(outstream, " └── Bound I/O: ");
679
680 for (k = 0; k < io_binding_count; k++)
681 {
682 if (k > 0)
683 {
684 fprintf(outstream, ", ");
685 }
686
687 fprintf(outstream, "%s", io_bindings[k]->getName());
688 }
689
690 fprintf(outstream, "\n");
691 }
692 }
693 }
694
695 if (has_unbound)
696 {
697 fprintf(outstream, "\n");
698 }
699
700 // Show ConfigIO objects and their bindings
701
702 io_count = inspector->getIOCount();
703 has_unbound = false;
704
705 for (i = 0; i < io_count; i++)
706 {
707 io = inspector->getIO(i);
708 if (io == nullptr)
709 {
710 continue;
711 }
712
713 // Check if this is a ConfigIO object
714
715 if (io->getCls() == CIOCommon::IO_CLASS_CONFIG)
716 {
717 const CIOConfig *cfg_io = static_cast<const CIOConfig *>(io);
718
719 if (!has_unbound)
720 {
721 fprintf(outstream, "ConfigIO objects:\n");
722 has_unbound = true;
723 }
724
725 fprintf(outstream, " * %s\n", io->getName());
726
727 if (!cfg_io->map.empty())
728 {
729 for (const auto &[id, cfg_bound_obj] : cfg_io->map)
730 {
731 if (cfg_bound_obj)
732 {
733 const char *type_str = "UNKNOWN";
734
735 switch (cfg_bound_obj->getType())
736 {
737 case SObjectId::OBJTYPE_IO:
738 type_str = "IO";
739 break;
740 case SObjectId::OBJTYPE_PROG:
741 type_str = "PROG";
742 break;
743 case SObjectId::OBJTYPE_PROTO:
744 type_str = "PROTO";
745 break;
746 }
747
748 fprintf(outstream,
749 " └── Configures %s: %s\n",
750 type_str,
751 cfg_bound_obj->getName());
752 }
753 }
754 }
755 }
756 }
757
758 if (has_unbound)
759 {
760 fprintf(outstream, "\n");
761 has_unbound = false;
762 }
763
764 // Show unbound IO objects (excluding ConfigIO)
765
766 for (i = 0; i < io_count; i++)
767 {
768 io = inspector->getIO(i);
769 if (io == nullptr)
770 {
771 continue;
772 }
773
774 // Skip ConfigIO objects (already shown above)
775
776 if (io->getCls() == CIOCommon::IO_CLASS_CONFIG)
777 {
778 continue;
779 }
780
781 is_bound = false;
782
783 // Check if bound to PROTO
784
785 for (j = 0; j < proto_count; j++)
786 {
787 binding_count = inspector->getProtoBindings(j, bound_objs, 128);
788
789 for (k = 0; k < binding_count; k++)
790 {
791 if (bound_objs[k]->getIdV() == io->getIdV())
792 {
793 is_bound = true;
794 break;
795 }
796 }
797
798 if (is_bound)
799 {
800 break;
801 }
802 }
803
804 // Check if bound to PROG
805
806 if (!is_bound)
807 {
808 for (j = 0; j < prog_count; j++)
809 {
810 io_binding_count = inspector->getProgIOBindings(j, io_bindings, 128);
811
812 for (k = 0; k < io_binding_count; k++)
813 {
814 if (io_bindings[k]->getIdV() == io->getIdV())
815 {
816 is_bound = true;
817 break;
818 }
819 }
820
821 if (is_bound)
822 {
823 break;
824 }
825 }
826 }
827
828 if (!is_bound)
829 {
830 if (!has_unbound)
831 {
832 fprintf(outstream, "Unbound I/O objects:\n");
833 has_unbound = true;
834 }
835
836 fprintf(outstream, " * %s\n", io->getName());
837 }
838 }
839
840 if (has_unbound)
841 {
842 fprintf(outstream, "\n");
843 }
844}
845
846void CProtoShellPretty::cmdStats(const char *arg)
847{
848 CDevInspector *inspector;
849 size_t io_count;
850# ifdef CONFIG_DAWN_IO_HAS_STATS
851 uint32_t total_reads;
852 uint32_t total_writes;
853 uint32_t total_errors;
854 const CIOCommon *most_reads;
855 const CIOCommon *most_writes;
856 uint32_t max_reads;
857 uint32_t max_writes;
858 bool has_errors;
859 size_t i;
860 const CIOCommon *io;
861 const CIOCommon::IOStats *stats;
862# endif
863
864 (void)arg;
865
866 inspector = CDevInspector::getInst();
867
868 fprintf(outstream, "\n");
869 fprintf(outstream, "I/O Statistics\n");
870 fprintf(outstream, "==============\n\n");
871
872 io_count = inspector->getIOCount();
873
874 if (io_count == 0)
875 {
876 fprintf(outstream, "No I/O objects registered\n");
877 return;
878 }
879
880# ifdef CONFIG_DAWN_IO_HAS_STATS
881 // Aggregate statistics
882
883 total_reads = 0;
884 total_writes = 0;
885 total_errors = 0;
886
887 // Track most active objects
888
889 most_reads = nullptr;
890 most_writes = nullptr;
891 max_reads = 0;
892 max_writes = 0;
893
894 // Process all IO objects
895
896 for (i = 0; i < io_count; i++)
897 {
898 io = inspector->getIO(i);
899 if (io == nullptr)
900 {
901 continue;
902 }
903
904 stats = &io->getStats();
905 total_reads += stats->read_count;
906 total_writes += stats->write_count;
907 total_errors += stats->error_count;
908
909 if (stats->read_count > max_reads)
910 {
911 max_reads = stats->read_count;
912 most_reads = io;
913 }
914
915 if (stats->write_count > max_writes)
916 {
917 max_writes = stats->write_count;
918 most_writes = io;
919 }
920 }
921
922 // Display summary
923
924 fprintf(outstream, "Summary\n");
925 fprintf(outstream, "-------\n");
926 fprintf(outstream, " Total I/O Objects: %zu\n", io_count);
927 fprintf(outstream, " Total Reads: %" PRIu32 "\n", total_reads);
928 fprintf(outstream, " Total Writes: %" PRIu32 "\n", total_writes);
929 fprintf(outstream, " Total Errors: %" PRIu32 "\n", total_errors);
930 fprintf(outstream, "\n");
931
932 // Display most active objects
933
934 if (most_reads && max_reads > 0)
935 {
936 fprintf(outstream, "Most Read I/O\n");
937 fprintf(outstream, "-------------\n");
938 fprintf(outstream, " Name: %s\n", most_reads->getName());
939 fprintf(outstream, " Object ID: 0x%08" PRIx32 "\n", most_reads->getIdV());
940 fprintf(outstream, " Read Count: %" PRIu32 "\n", max_reads);
941 fprintf(outstream, "\n");
942 }
943
944 if (most_writes && max_writes > 0)
945 {
946 fprintf(outstream, "Most Written I/O\n");
947 fprintf(outstream, "----------------\n");
948 fprintf(outstream, " Name: %s\n", most_writes->getName());
949 fprintf(outstream, " Object ID: 0x%08" PRIx32 "\n", most_writes->getIdV());
950 fprintf(outstream, " Write Count: %" PRIu32 "\n", max_writes);
951 fprintf(outstream, "\n");
952 }
953
954 // Display objects with errors
955
956 has_errors = false;
957
958 for (i = 0; i < io_count; i++)
959 {
960 io = inspector->getIO(i);
961 if (io == nullptr)
962 {
963 continue;
964 }
965
966 stats = &io->getStats();
967
968 if (stats->error_count > 0)
969 {
970 if (!has_errors)
971 {
972 fprintf(outstream, "I/O Objects with Errors\n");
973 fprintf(outstream, "-----------------------\n");
974 has_errors = true;
975 }
976
977 fprintf(outstream,
978 " %-14s 0x%08" PRIx32 " - %" PRIu32 " errors\n",
979 io->getName(),
980 io->getIdV(),
981 stats->error_count);
982 }
983 }
984
985 if (!has_errors)
986 {
987 fprintf(outstream, "No errors recorded.\n");
988 }
989
990 fprintf(outstream, "\n");
991# else
992 fprintf(outstream,
993 "Statistics tracking is disabled.\n"
994 "Enable CONFIG_DAWN_IO_HAS_STATS to track I/O statistics.\n\n");
995# endif
996}
997
998#endif // CONFIG_DAWN_PROTO_SHELL_INSPECT
Global registry for object inspection.
Definition inspector.hxx:38
size_t getProtoBindings(size_t proto_index, const CObject **obj_list, size_t max_size) const
Get object bindings for PROTO object.
size_t getProtoCount() const
Get number of PROTO objects.
Definition inspector.cxx:65
size_t getProgCount() const
Get number of PROG objects.
Definition inspector.cxx:55
const CObject * getProg(size_t index) const
Get PROG object by index.
Definition inspector.cxx:92
const CObject * findObject(uint32_t objid) const
Find object by ID.
const CIOCommon * getIO(size_t index) const
Get IO object by index.
Definition inspector.cxx:75
size_t getProgIOBindings(size_t prog_index, const CIOCommon **io_list, size_t max_size) const
Get IO bindings for PROG object.
size_t getIOCount() const
Get number of IO objects.
Definition inspector.cxx:45
const CObject * getProto(size_t index) const
Get PROTO object by index.
Base class for all I/O objects.
Definition common.hxx:27
virtual size_t getDataDim() const =0
Get data vector dimension.
virtual size_t getDataSize() const =0
Get data size in bytes.
virtual bool isRead() const =0
Check if IO supports read operations.
Configuration I/O for runtime object management.
Definition config.hxx:24
std::map< uint32_t, CObject * > map
Map of object ID to bound CObject pointers.
Definition config.hxx:125
Base class for all Dawn objects (IOs, Programs, Protocols).
Definition object.hxx:28
uint8_t getType() const
Get object type field.
Definition object.cxx:165
uint16_t getPriv() const
Get instance/private data field.
Definition object.cxx:185
uint16_t getCls() const
Get object class field.
Definition object.cxx:170
uint8_t getFlags() const
Get type-specific flags field.
Definition object.cxx:180
virtual EObjectState getState() const
Get current operational state.
Definition object.hxx:183
SObjectId::ObjectId getIdV() const
Get object identifier as raw 32-bit value.
Definition object.cxx:155
size_t getDtypeSize() const
Get size of this object's data type.
Definition object.cxx:195
uint8_t getDtype() const
Get data type field.
Definition object.cxx:175
bool getCfgFlag() const
Check if configuration flag is set.
Definition object.cxx:160
Out-of-tree user-extension hooks for Dawn.
Definition bindable.hxx:13