Explorar o código

application: refactor cpuinfo to show more and ease porting

- show IREGION INFO
- ease OpenOCD porting

Signed-off-by: qiujiandong <qiujiandong@nucleisys.com>
qiujiandong hai 4 meses
pai
achega
7ea39b0b50

+ 675 - 0
application/baremetal/cpuinfo/cpuinfo.c

@@ -0,0 +1,675 @@
+/* NOTE: Predefine macro `CIF_PRINTF` before include `cpuinfo.h`
+ * to replace the default `CIF_PRINTF` function.
+ */
+#include "cpuinfo.h"
+
+#define BIT(ofs) (0x1U << (ofs))
+#define EXTENSION_NUM (26)
+#define POW2(n) (1U << (n))
+#define LINESZ(n) ((n) > 0U ? POW2((n) - 1) : 0)
+
+/* IREGION Offsets */
+#define IREGION_IINFO_OFS (0x0)
+#define IREGION_DEBUG_OFS (0x10000)
+#define IREGION_ECLIC_OFS (0x20000)
+#define IREGION_TIMER_OFS (0x30000)
+#define IREGION_SMP_OFS (0x40000)
+#define IREGION_IDU_OFS (0x50000)
+#define IREGION_PL2_OFS (0x60000)
+#define IREGION_DPREFETCH_OFS (0x70000)
+#define IREGION_PLIC_OFS (0x4000000)
+
+/* Check register field with default field name print */
+#define CHECK_FIELD_DFT(reg, field)                                            \
+    if (reg.b.field) {                                                         \
+        CIF_PRINTF(" %s", #field);                                             \
+    }
+/* Check register field with string specified */
+#define CHECK_FIELD(reg, field, str)                                           \
+    if (reg.b.field) {                                                         \
+        CIF_PRINTF(" %s", str);                                                \
+    }
+/* Show register value */
+#define SHOW_VALUE(reg, field)                                                 \
+    CIF_PRINTF("                      %s=%u\r\n", #field, reg.b.field);
+
+static void show_isa(CIF_XLEN_Type xlen, U32_CSR_MISA_Type misa,
+                     U32_CSR_MCFG_INFO_Type mcfg);
+static void show_mcfg(const CPU_CSR_Group *csrs);
+static void show_micfg_mdcfg(U32_CSR_MCFG_INFO_Type mcfg,
+                             U32_CSR_MICFG_INFO_Type micfg,
+                             U32_CSR_MDCFG_INFO_Type mdcfg);
+static void show_mtlbcfg(U32_CSR_MCFG_INFO_Type mcfg,
+                         U32_CSR_MTLBCFG_INFO_Type mtlbcfg);
+static void show_iregion(const CPU_CSR_Group *csrs);
+static void show_mfiocfg(U32_CSR_MCFG_INFO_Type mcfg,
+                         U64_CSR_MFIOCFG_INFO_Type mfiocfg);
+static void show_mppicfg(U32_CSR_MCFG_INFO_Type mcfg,
+                         U64_CSR_MPPICFG_INFO_Type mppicfg);
+
+static void show_prefetch_cfg(IINFO_Type *iinfo);
+static void show_isa_support(IINFO_Type *iinfo);
+static void show_mvlm_cfg(IINFO_Type *iinfo);
+static void show_flash_bus(IINFO_Type *iinfo);
+static void show_mem_region_cfg(IINFO_Type *iinfo);
+static void show_mcppi_cfg(IINFO_Type *iinfo);
+static void show_cmo(IINFO_Type *iinfo);
+static void show_performance_cfg(IINFO_Type *iinfo);
+static void show_misc_cfg(IINFO_Type *iinfo);
+
+static char *cvt_size(uint32_t size);
+static void show_cache_info(uint32_t set, uint32_t way, uint32_t lsize,
+                            uint32_t ecc);
+
+void show_cpuinfo(CIF_XLEN_Type xlen, const CPU_CSR_Group *csrs)
+{
+    CIF_PRINTF("\r\n-----Nuclei RISC-V CPU Configuration Information-----\r\n");
+
+    /* ID and version */
+    CIF_PRINTF("         MARCHID: 0x%04x\r\n", csrs->marchid.d);
+    CIF_PRINTF("          MIMPID: 0x%06x\r\n", csrs->mimpid.d);
+
+    /* ISA */
+    show_isa(xlen, csrs->misa, csrs->mcfginfo);
+    /* Support */
+    show_mcfg(csrs);
+    /* ILM, DLM, I/D Cache */
+    show_micfg_mdcfg(csrs->mcfginfo, csrs->micfginfo, csrs->mdcfginfo);
+    /* TLB */
+    show_mtlbcfg(csrs->mcfginfo, csrs->mtlbcfginfo);
+    /* FIO */
+    show_mfiocfg(csrs->mcfginfo, csrs->mfiocfginfo);
+    /* PPI */
+    show_mppicfg(csrs->mcfginfo, csrs->mppicfginfo);
+    /* IREGION */
+    show_iregion(csrs);
+
+    CIF_PRINTF("-----End of Nuclei CPU INFO-----\r\n");
+}
+
+static void show_isa(CIF_XLEN_Type xlen, U32_CSR_MISA_Type misa,
+                     U32_CSR_MCFG_INFO_Type mcfg)
+{
+    CIF_PRINTF("             ISA:");
+    if (xlen == CIF_XLEN_32) {
+        CIF_PRINTF(" RV32");
+    } else if (xlen == CIF_XLEN_64) {
+        CIF_PRINTF(" RV64");
+    } else {
+        CIF_PRINTF(" Unknown");
+    }
+    for (int i = 0; i < EXTENSION_NUM; i++) {
+        if (misa.d & BIT(i)) {
+            if ('X' == ('A' + i)) {
+                CIF_PRINTF(" NICE");
+            } else {
+                CIF_PRINTF(" %c", 'A' + i);
+            }
+        }
+    }
+    CHECK_FIELD(mcfg, dsp_n1, "Xxldspn1x");
+    CHECK_FIELD(mcfg, dsp_n2, "Xxldspn2x");
+    CHECK_FIELD(mcfg, dsp_n3, "Xxldspn3x");
+    if (mcfg.b.zc_xlcz) {
+        if (mcfg.b.xlcz == 0) {
+            CIF_PRINTF(" Zc Xxlcz");
+        } else {
+            CIF_PRINTF(" Zc");
+        }
+    }
+    CHECK_FIELD(mcfg, zilsd, "Zilsd");
+    CIF_PRINTF("\r\n");
+}
+
+static void show_mcfg(const CPU_CSR_Group *csrs)
+{
+    if (!csrs->mcfg_exist) {
+        return;
+    }
+
+    U32_CSR_MCFG_INFO_Type mcfg = csrs->mcfginfo;
+    CIF_PRINTF("            MCFG:");
+    CHECK_FIELD(mcfg, tee, "TEE")
+    CHECK_FIELD(mcfg, ecc, "ECC")
+    CHECK_FIELD(mcfg, eclic, "ECLIC")
+    CHECK_FIELD(mcfg, plic, "PLIC")
+    CHECK_FIELD(mcfg, fio, "FIO")
+    CHECK_FIELD(mcfg, ppi, "PPI")
+    CHECK_FIELD(mcfg, nice, "NICE")
+    CHECK_FIELD(mcfg, ilm, "ILM")
+    CHECK_FIELD(mcfg, dlm, "DLM")
+    CHECK_FIELD(mcfg, icache, "ICACHE")
+    CHECK_FIELD(mcfg, dcache, "DCACHE")
+    CHECK_FIELD(mcfg, smp, "SMP")
+    CHECK_FIELD(mcfg, iregion, "IREGION")
+    CHECK_FIELD(mcfg, sec_mode, "SMWG")
+    CHECK_FIELD(mcfg, etrace, "ETRACE")
+    CHECK_FIELD(mcfg, vnice, "VNICE")
+    CHECK_FIELD(mcfg, sstc, "SSTC")
+    switch (mcfg.b.safety_mecha) {
+        case 0b00:
+            CIF_PRINTF(" No-Safety-Mechanism");
+            break;
+        case 0b01:
+            CIF_PRINTF(" Lockstep");
+            break;
+        case 0b10:
+            CIF_PRINTF(" Lockstep+SplitMode");
+            break;
+        case 0b11:
+            CIF_PRINTF(" ASIL-B");
+            break;
+        default:
+            break;
+    }
+    if (csrs->misa.b.V) {
+        switch (mcfg.b.vpu_degree) {
+            case 0b00:
+                CIF_PRINTF(" DLEN=VLEN/2");
+                break;
+            case 0b01:
+                CIF_PRINTF(" DLEN=VLEN");
+                break;
+            default:
+                break;
+        }
+    }
+    CIF_PRINTF("\r\n");
+}
+
+static void show_micfg_mdcfg(U32_CSR_MCFG_INFO_Type mcfg,
+                             U32_CSR_MICFG_INFO_Type micfg,
+                             U32_CSR_MDCFG_INFO_Type mdcfg)
+{
+    /* ILM */
+    if (mcfg.b.ilm) {
+        CIF_PRINTF("             ILM:");
+        CIF_PRINTF(" %s", cvt_size(POW2(micfg.b.lm_size + 7)));
+        CHECK_FIELD(micfg, lm_xonly, "execute-only");
+        CHECK_FIELD(micfg, lm_ecc, "has-ecc");
+        CIF_PRINTF("\r\n");
+    }
+    /* DLM */
+    if (mcfg.b.dlm) {
+        CIF_PRINTF("             DLM:");
+        CIF_PRINTF(" %s", cvt_size(POW2(mdcfg.b.lm_size + 7)));
+        CHECK_FIELD(mdcfg, lm_ecc, "has-ecc");
+        CIF_PRINTF("\r\n");
+    }
+    /* ICACHE */
+    if (mcfg.b.icache) {
+        CIF_PRINTF("          ICACHE:");
+        show_cache_info(POW2(micfg.b.set + 3), micfg.b.way + 1,
+                        POW2(micfg.b.lsize + 2), mcfg.b.ecc);
+    }
+    /* DCACHE */
+    if (mcfg.b.dcache) {
+        CIF_PRINTF("          DCACHE:");
+        show_cache_info(POW2(mdcfg.b.set + 3), mdcfg.b.way + 1,
+                        POW2(mdcfg.b.lsize + 2), mcfg.b.ecc);
+    }
+}
+
+static void show_mtlbcfg(U32_CSR_MCFG_INFO_Type mcfg,
+                         U32_CSR_MTLBCFG_INFO_Type mtlbcfg)
+{
+    /* TLB only present with MMU, when PLIC present MMU will present */
+    if (mcfg.b.plic) {
+        if (mtlbcfg.nb.mapping == 1) {
+            CIF_PRINTF("             TLB:");
+            CIF_PRINTF(" MainTLB(entry=%u,way=%u,ecc=%u)",
+                       POW2(mtlbcfg.nb.set + 3), mtlbcfg.nb.way + 1,
+                       mtlbcfg.nb.ecc);
+            CIF_PRINTF(" ITLB(entry=%u) DTLB(entry=%u)\r\n",
+                       mtlbcfg.nb.i_size + 1, mtlbcfg.nb.d_size + 1);
+        } else {
+            CIF_PRINTF("             TLB:");
+            CIF_PRINTF(" MainTLB(entry=%u,way=%u,ecc=%u)",
+                       POW2(mtlbcfg.b.set + 3), mtlbcfg.b.way + 1,
+                       mtlbcfg.b.ecc);
+            CIF_PRINTF(" ITLB(entry=%u) DTLB(entry=%u)\r\n",
+                       LINESZ(mtlbcfg.b.i_size), LINESZ(mtlbcfg.b.d_size));
+        }
+    }
+}
+
+static void show_iregion(const CPU_CSR_Group *csrs)
+{
+    U32_CSR_MCFG_INFO_Type mcfg = csrs->mcfginfo;
+    if (!mcfg.b.iregion) {
+        return;
+    }
+
+    CIF_PRINTF("         IREGION:");
+    U64_CSR_MIRGB_INFO_Type mirgb = csrs->mirgbinfo;
+    unsigned long iregion_base = mirgb.d & (~0x3FF);
+    CIF_PRINTF(" %#lx", iregion_base);
+    CIF_PRINTF(" %s\r\n", cvt_size(POW2(mirgb.b.iregion_size + 9)));
+    CIF_PRINTF("                  Unit        Size        Address\r\n");
+    CIF_PRINTF("                  INFO        64KB        %#lx\r\n",
+               iregion_base + IREGION_IINFO_OFS);
+    CIF_PRINTF("                  DEBUG       64KB        %#lx\r\n",
+               iregion_base + IREGION_DEBUG_OFS);
+    if (mcfg.b.eclic) {
+        CIF_PRINTF("                  ECLIC       64KB        %#lx\r\n",
+                   iregion_base + IREGION_ECLIC_OFS);
+    }
+    CIF_PRINTF("                  TIMER       64KB        %#lx\r\n",
+               iregion_base + IREGION_TIMER_OFS);
+    if (mcfg.b.smp) {
+        CIF_PRINTF("                  SMP         64KB        %#lx\r\n",
+                   iregion_base + IREGION_SMP_OFS);
+    }
+    U32_CSR_SMP_CFG_Type smp_cfg =
+        *(U32_CSR_SMP_CFG_Type *)(iregion_base + IREGION_SMP_OFS + 4);
+    /* If has eclic and has equal or more than 1 core, CIDU will present
+     * The actual core number is `smp_core_num + 1` */
+    if (mcfg.b.eclic && (smp_cfg.b.smp_core_num >= 1)) {
+        CIF_PRINTF("                  CIDU        64KB        %#lx\r\n",
+                   iregion_base + IREGION_IDU_OFS);
+    }
+    if (mcfg.b.plic) {
+        CIF_PRINTF("                  PLIC        64MB        %#lx\r\n",
+                   iregion_base + IREGION_PLIC_OFS);
+    }
+    /* SMP */
+    if (mcfg.b.smp) {
+        CIF_PRINTF("         SMP_CFG:");
+        CIF_PRINTF(" CC_PRESENT=%d", smp_cfg.b.cc);
+        CIF_PRINTF(" SMP_NUM=%d", smp_cfg.b.smp_core_num + 1);
+        CIF_PRINTF(" IOCP_NUM=%d", smp_cfg.b.iocp_num);
+        CIF_PRINTF(" PMON_NUM=%d", smp_cfg.b.pmon_num);
+        CIF_PRINTF("\r\n");
+    }
+    /* ECLIC */
+    if (mcfg.b.eclic) {
+        ECLIC_Type *eclic = (ECLIC_Type *)(iregion_base + IREGION_ECLIC_OFS);
+        U32_CSR_ECLIC_INFO_Type eclic_info = eclic->info;
+        CIF_PRINTF("           ECLIC:");
+        CIF_PRINTF(" VERSION=0x%x", eclic_info.b.version);
+        CIF_PRINTF(" NUM_INTERRUPT=%u", eclic_info.b.num_interrupt);
+        CIF_PRINTF(" CLICINTCTLBITS=%u", eclic_info.b.clicintctlbits);
+        CIF_PRINTF(" MTH=%u", eclic->mth);
+        CIF_PRINTF(" NLBITS=%u", (eclic->cfg & 0x1E) >> 1);
+        CIF_PRINTF("\r\n");
+    }
+    /* L2CACHE */
+    if (smp_cfg.b.cc) {
+        U32_CSR_CC_CFG_Type cc_cfg =
+            *(U32_CSR_CC_CFG_Type *)(iregion_base + IREGION_SMP_OFS + 8);
+        CIF_PRINTF("         L2CACHE:");
+        show_cache_info(POW2(cc_cfg.b.set), cc_cfg.b.way + 1,
+                        POW2(cc_cfg.b.lsize + 2), cc_cfg.b.ecc);
+    }
+    /* IREGION INFO */
+    unsigned long iinfo_base = iregion_base + IREGION_IINFO_OFS;
+    CIF_PRINTF("     INFO-Detail:\r\n");
+    /* MPASIZE */
+    uint32_t mpasize = csrs->iinfo->mpasize;
+    CIF_PRINTF("                  mpasize : %u\r\n", mpasize);
+    /* prefetch related registers */
+    show_prefetch_cfg(csrs->iinfo);
+    /* ISA_SUPPORT VPU_CFG_INFO */
+    show_isa_support(csrs->iinfo);
+    /* MVLM_CFG */
+    show_mvlm_cfg(csrs->iinfo);
+    /* FLASH_BASE_ADDR */
+    show_flash_bus(csrs->iinfo);
+    /* MEM_REGION_CFG */
+    show_mem_region_cfg(csrs->iinfo);
+    /* MCPPI_CFG */
+    show_mcppi_cfg(csrs->iinfo);
+    /* CMO_INFO */
+    show_cmo(csrs->iinfo);
+    /* PERFORMANCE_CFG */
+    show_performance_cfg(csrs->iinfo);
+    /* MERGEL1DCTRL and ACCESS_CTRL */
+    show_misc_cfg(csrs->iinfo);
+}
+
+static void show_mfiocfg(U32_CSR_MCFG_INFO_Type mcfg,
+                         U64_CSR_MFIOCFG_INFO_Type mfiocfg)
+{
+    if (mcfg.b.fio) {
+        CIF_PRINTF("             FIO:");
+        CIF_PRINTF(" %#lx", (unsigned long)mfiocfg.d & (~0x3FF));
+        CIF_PRINTF(" %s\r\n", cvt_size(POW2(mfiocfg.b.fio_size + 9)));
+    }
+}
+
+static void show_mppicfg(U32_CSR_MCFG_INFO_Type mcfg,
+                         U64_CSR_MPPICFG_INFO_Type mppicfg)
+{
+    if (mcfg.b.ppi) {
+        CIF_PRINTF("             PPI:");
+        CIF_PRINTF(" %#lx", (unsigned long)mppicfg.d & (~0x3FF));
+        CIF_PRINTF(" %s\r\n", cvt_size(POW2(mppicfg.b.ppi_size + 9)));
+    }
+}
+
+static void show_prefetch_cfg(IINFO_Type *iinfo)
+{
+    IINFO_PFL1INFO_Type pfl1info;
+    pfl1info.d = iinfo->pfl1info;
+    if (pfl1info.b.pf_cfg) {
+        CIF_PRINTF("                  prefetch: present\r\n");
+        const char *pf_cfg[] = {"none", "normal", "high performance"};
+        if (pfl1info.b.pf_cfg < 3) {
+            CIF_PRINTF("                      prefetch_mode: %s\r\n",
+                       pf_cfg[pfl1info.b.pf_cfg]);
+        }
+        if (iinfo->pfl1dctrl4 & BIT(0)) {
+            CIF_PRINTF("                      status: enable\r\n");
+        } else {
+            CIF_PRINTF("                      status: disable\r\n");
+        }
+        if (pfl1info.b.pf_ver) {
+            CIF_PRINTF("                      version=%u\r\n",
+                       pfl1info.b.pf_ver);
+        }
+
+        /* prefetch config */
+        IINFO_PFL1DCTRL1_Type pfl1dctrl1;
+        IINFO_PFL1DCTRL2_Type pfl1dctrl2;
+        IINFO_PFL1DCTRL3_Type pfl1dctrl3;
+        pfl1dctrl1.d = iinfo->pfl1dctrl1;
+        pfl1dctrl2.d = iinfo->pfl1dctrl2;
+        pfl1dctrl3.d = iinfo->pfl1dctrl3;
+        SHOW_VALUE(pfl1info, l2_pf_lbuf_num);
+        SHOW_VALUE(pfl1info, l2_pf_dbuf_num);
+        SHOW_VALUE(pfl1dctrl1, l1d_ena);
+        SHOW_VALUE(pfl1dctrl1, cc_ena);
+        SHOW_VALUE(pfl1dctrl1, scalar_ena);
+        SHOW_VALUE(pfl1dctrl1, vector_ena);
+        SHOW_VALUE(pfl1dctrl1, write_pref_ena);
+        SHOW_VALUE(pfl1dctrl1, cross_page_pref_ena);
+        SHOW_VALUE(pfl1dctrl1, pref_conflict_stop_th);
+        SHOW_VALUE(pfl1dctrl1, pref_conflict_decr_sel);
+        SHOW_VALUE(pfl1dctrl2, degree_incr_th);
+        SHOW_VALUE(pfl1dctrl2, degree_decr_th);
+        SHOW_VALUE(pfl1dctrl2, next_line_ena_th);
+        SHOW_VALUE(pfl1dctrl2, write_noalloc_l1_th);
+        SHOW_VALUE(pfl1dctrl2, write_noalloc_l2_th);
+        SHOW_VALUE(pfl1dctrl3, max_stream_l1_degree);
+        SHOW_VALUE(pfl1dctrl3, max_stream_l2_degree);
+        SHOW_VALUE(pfl1dctrl3, max_stride_cplx_l1_degree);
+        SHOW_VALUE(pfl1dctrl3, max_stride_cplx_l2_degree);
+    } else {
+        CIF_PRINTF("                  prefetch: absent\r\n");
+    }
+}
+
+static void show_isa_support(IINFO_Type *iinfo)
+{
+    IINFO_ISA_SUPPORT0_Type isa_support0;
+    IINFO_ISA_SUPPORT1_Type isa_support1;
+    isa_support0.d = iinfo->isa_support0;
+    isa_support1.d = iinfo->isa_support1;
+
+    if (isa_support0.b.exist || isa_support1.b.exist) {
+        CIF_PRINTF("                  isa supported: present\r\n");
+        CIF_PRINTF("                      extension_list:");
+        if (isa_support0.b.exist) {
+            CHECK_FIELD_DFT(isa_support0, vector);
+            CHECK_FIELD_DFT(isa_support0, smepmp);
+            CHECK_FIELD_DFT(isa_support0, sscofpmf);
+            CHECK_FIELD_DFT(isa_support0, zfh);
+            CHECK_FIELD_DFT(isa_support0, zfhmin);
+            CHECK_FIELD_DFT(isa_support0, zfa);
+            CHECK_FIELD_DFT(isa_support0, svnapot);
+            CHECK_FIELD_DFT(isa_support0, svpbmt);
+            CHECK_FIELD_DFT(isa_support0, svinval);
+            CHECK_FIELD_DFT(isa_support0, bf16);
+            CHECK_FIELD_DFT(isa_support0, zimop);
+            CHECK_FIELD_DFT(isa_support0, zcmop);
+            CHECK_FIELD_DFT(isa_support0, zicond);
+            CHECK_FIELD_DFT(isa_support0, zihintntl);
+            CHECK_FIELD_DFT(isa_support0, zihintpause);
+            CHECK_FIELD_DFT(isa_support0, smrnmi);
+            CHECK_FIELD_DFT(isa_support0, zihpm);
+            CHECK_FIELD_DFT(isa_support0, smcntrpmf);
+            CHECK_FIELD_DFT(isa_support0, zicntr);
+            CHECK_FIELD_DFT(isa_support0, zawrs);
+        }
+        if (isa_support1.b.exist) {
+            CHECK_FIELD_DFT(isa_support1, ssqosid);
+            CHECK_FIELD_DFT(isa_support1, zicflip);
+            CHECK_FIELD_DFT(isa_support1, zicfiss);
+            CHECK_FIELD_DFT(isa_support1, smctr);
+            CHECK_FIELD_DFT(isa_support1, zacas);
+            CHECK_FIELD_DFT(isa_support1, zabha);
+            CHECK_FIELD_DFT(isa_support1, smdbltrp);
+            CHECK_FIELD_DFT(isa_support1, ssdbltrp);
+            CHECK_FIELD_DFT(isa_support1, smcdeleg);
+            CHECK_FIELD_DFT(isa_support1, smmpm);
+            CHECK_FIELD_DFT(isa_support1, smnpm);
+            CHECK_FIELD_DFT(isa_support1, ssnpm);
+            CHECK_FIELD_DFT(isa_support1, smstateen);
+            CHECK_FIELD_DFT(isa_support1, sstateen);
+            CHECK_FIELD_DFT(isa_support1, smcsrind);
+            CHECK_FIELD_DFT(isa_support1, sscsrind);
+            CHECK_FIELD_DFT(isa_support1, svadu);
+        }
+        CIF_PRINTF("\r\n");
+    } else {
+        CIF_PRINTF("                  isa supported: absent\r\n");
+    }
+
+    /* VPU related extensions */
+    if (isa_support0.b.exist && isa_support0.b.vector) {
+        CIF_PRINTF("                  vpu: present\r\n");
+        CIF_PRINTF("                      vpu_extension_list:");
+        CHECK_FIELD_DFT(isa_support0, vector_b);
+        CHECK_FIELD_DFT(isa_support0, vector_k);
+        CHECK_FIELD_DFT(isa_support0, zve32x);
+        CHECK_FIELD_DFT(isa_support0, zve32f);
+        CHECK_FIELD_DFT(isa_support0, zve64x);
+        CHECK_FIELD_DFT(isa_support0, zve64f);
+        CHECK_FIELD_DFT(isa_support0, zve64d);
+        CHECK_FIELD_DFT(isa_support0, zvfh);
+        CHECK_FIELD_DFT(isa_support0, zvfhmin);
+        CIF_PRINTF("\r\n");
+
+        uint32_t vpu_cfg_info = iinfo->vpu_cfg_info;
+        CIF_PRINTF("                      noseg_noshuf=%u\r\n",
+                   (unsigned int)(vpu_cfg_info & BIT(0)));
+        CIF_PRINTF("                      elen64=%u\r\n",
+                   (unsigned int)(vpu_cfg_info & BIT(1)) >> 1);
+    } else {
+        CIF_PRINTF("                  vpu: absent\r\n");
+    }
+}
+
+static void show_mvlm_cfg(IINFO_Type *iinfo)
+{
+    IINFO_MVLM_CFG_LO_Type mvlm_cfg_lo;
+    mvlm_cfg_lo.d = iinfo->mvlm_cfg_lo;
+    if (mvlm_cfg_lo.b.vlm) {
+        CIF_PRINTF("                  vlm: present\r\n");
+        IINFO_MVLM_CFG_HI_Type mvlm_cfg_hi = iinfo->mvlm_cfg_hi;
+        unsigned long vlm_base =
+            (uint64_t)mvlm_cfg_hi << 32 | (mvlm_cfg_lo.d & (~0x3FF));
+        CIF_PRINTF("                      base=0x%lx\r\n", vlm_base);
+        CIF_PRINTF("                      size=%s\r\n",
+                   cvt_size(POW2(mvlm_cfg_lo.b.vlm_size + 9)));
+    } else {
+        CIF_PRINTF("                  vlm: absent\r\n");
+    }
+}
+
+static void show_flash_bus(IINFO_Type *iinfo)
+{
+    IINFO_FLASH_BASE_ADDR_LO_Type addr_lo;
+    addr_lo.d = iinfo->flash_base_addr_lo;
+    if (addr_lo.b.flash) {
+        CIF_PRINTF("                  flash bus: present\r\n");
+        IINFO_FLASH_BASE_ADDR_HI_Type addr_hi = iinfo->flash_base_addr_hi;
+        unsigned long flash_base =
+            (uint64_t)addr_hi << 32 | (addr_lo.d & (~0x3FF));
+        CIF_PRINTF("                      base=0x%lx\r\n", flash_base);
+        CIF_PRINTF("                      size=%s\r\n",
+                   cvt_size(addr_lo.b.flash_size + 9));
+    } else {
+        CIF_PRINTF("                  flash bus: absent\r\n");
+    }
+}
+
+static void show_mem_region_cfg(IINFO_Type *iinfo)
+{
+    IINFO_MEM_REGION_CFG_LO_Type region_lo;
+    region_lo.d = iinfo->mem_region0_cfg_lo;
+    if (region_lo.b.exist) {
+        CIF_PRINTF("                  mem_region0: present\r\n");
+        IINFO_MEM_REGION_CFG_HI_Type region_hi = iinfo->mem_region0_cfg_hi;
+        unsigned long region_base =
+            (uint64_t)region_hi << 32 | (region_lo.d & (~0x3FF));
+        if (region_lo.b.mem_region_ena) {
+            CIF_PRINTF("                      status: enable\r\n");
+        } else {
+            CIF_PRINTF("                      status: disable\r\n");
+        }
+        CIF_PRINTF("                      base=0x%lx\r\n", region_base);
+        CIF_PRINTF("                      size=%s\r\n",
+                   cvt_size(region_lo.b.mem_region_size + 9));
+    } else {
+        CIF_PRINTF("                  mem_region0: absent\r\n");
+    }
+    region_lo.d = iinfo->mem_region1_cfg_lo;
+    if (region_lo.b.exist) {
+        CIF_PRINTF("                  mem_region1: present\r\n");
+        IINFO_MEM_REGION_CFG_HI_Type region_hi = iinfo->mem_region1_cfg_hi;
+        unsigned long region_base =
+            (uint64_t)region_hi << 32 | (region_lo.d & (~0x3FF));
+        if (region_lo.b.mem_region_ena) {
+            CIF_PRINTF("                      status: enable\r\n");
+        } else {
+            CIF_PRINTF("                      status: disable\r\n");
+        }
+        CIF_PRINTF("                      base=0x%lx\r\n", region_base);
+        CIF_PRINTF("                      size=%s\r\n",
+                   cvt_size(region_lo.b.mem_region_size + 9));
+    } else {
+        CIF_PRINTF("                  mem_region1: absent\r\n");
+    }
+}
+
+static void show_mcppi_cfg(IINFO_Type *iinfo)
+{
+    IINFO_MCPPI_CFG_LO_Type mcppi_lo;
+    mcppi_lo.d = iinfo->mcppi_cfg_lo;
+    if (mcppi_lo.b.exist) {
+        CIF_PRINTF("                  cppi: present\r\n");
+        IINFO_MCPPI_CFG_HI_Type mcppi_hi = iinfo->mcppi_cfg_hi;
+        unsigned long mcppi_base =
+            (uint64_t)mcppi_hi << 32 | (mcppi_lo.d & (~0x3FF));
+        if (mcppi_lo.b.cppi_ena) {
+            CIF_PRINTF("                      status: enable\r\n");
+        } else {
+            CIF_PRINTF("                      status: disable\r\n");
+        }
+        CIF_PRINTF("                      base=0x%lx\r\n", mcppi_base);
+        CIF_PRINTF("                      size=%s\r\n",
+                   cvt_size(mcppi_lo.b.cppi_size + 9));
+    } else {
+        CIF_PRINTF("                  cppi: absent\r\n");
+    }
+}
+
+static void show_cmo(IINFO_Type *iinfo)
+{
+    IINFO_MCMO_INFO_Type cmo_info;
+    cmo_info.d = iinfo->cmo_info;
+    if (cmo_info.b.cmo_cfg) {
+        CIF_PRINTF("                  cmo: present\r\n");
+        CIF_PRINTF("                      cbozero_size: %u Bytes\r\n",
+                   POW2(cmo_info.b.cbozero_size + 2));
+        CIF_PRINTF("                      cmo_size: %u Bytes\r\n",
+                   POW2(cmo_info.b.cmo_size + 2));
+        CIF_PRINTF("                      cmo_prefetch=%u\r\n",
+                   cmo_info.b.cmo_pft);
+    } else {
+        CIF_PRINTF("                  cmo: absent\r\n");
+    }
+}
+
+static void show_performance_cfg(IINFO_Type *iinfo)
+{
+    IINFO_PERFORMANCE_CFG0_Type performance_cfg0;
+    IINFO_PERFORMANCE_CFG1_Type performance_cfg1;
+    performance_cfg0.d = iinfo->performance_cfg0;
+    performance_cfg1.d = iinfo->performance_cfg1;
+
+    if (performance_cfg0.b.exist || performance_cfg1.b.exist) {
+        CIF_PRINTF("                  hw performance: present\r\n");
+        if (performance_cfg0.b.exist) {
+            const char *bus[] = {"ICB", "AXI", "AHBL"};
+            if (performance_cfg0.b.bus_type < 3) {
+                CIF_PRINTF("                      bus: %s\r\n",
+                           bus[performance_cfg0.b.bus_type]);
+            }
+            SHOW_VALUE(performance_cfg0, fpu_cycle);
+            SHOW_VALUE(performance_cfg0, high_div);
+            SHOW_VALUE(performance_cfg0, dcache_2stage);
+            SHOW_VALUE(performance_cfg0, delay_branch_flush);
+            SHOW_VALUE(performance_cfg0, dual_issue);
+            SHOW_VALUE(performance_cfg0, cross_4k);
+            SHOW_VALUE(performance_cfg0, dlm_2stage);
+            SHOW_VALUE(performance_cfg0, lsu_cut_fwd);
+            SHOW_VALUE(performance_cfg0, dsp_cycle);
+            SHOW_VALUE(performance_cfg0, ifu_cut_timing);
+            SHOW_VALUE(performance_cfg0, mem_cut_timing);
+            SHOW_VALUE(performance_cfg0, dcache_prefetch);
+            SHOW_VALUE(performance_cfg0, dcache_lbuf_num);
+            SHOW_VALUE(performance_cfg0, mul_cyc);
+        }
+        if (performance_cfg1.b.exist) {
+            SHOW_VALUE(performance_cfg1, vfpu_cyc);
+            SHOW_VALUE(performance_cfg1, bht_entry_width);
+            SHOW_VALUE(performance_cfg1, high_performance);
+            SHOW_VALUE(performance_cfg1, agu_quick_forward);
+            SHOW_VALUE(performance_cfg1, cau_fwd);
+            SHOW_VALUE(performance_cfg1, hpm_ver);
+        }
+    } else {
+        CIF_PRINTF("                  hw performance: absent\r\n");
+    }
+}
+
+static void show_misc_cfg(IINFO_Type *iinfo)
+{
+    IINFO_MERGEL1DCTRL_Type mergel1dctrl;
+    IINFO_ACCESS_CTRL_Type access_ctrl;
+    mergel1dctrl.d = iinfo->mergel1dctrl;
+    access_ctrl.d = iinfo->access_ctrl;
+    CIF_PRINTF("                  misc: \r\n");
+    SHOW_VALUE(mergel1dctrl, ws_tmout_max);
+    SHOW_VALUE(mergel1dctrl, nc_tmout_max);
+    SHOW_VALUE(mergel1dctrl, dev_store_early_ret);
+    SHOW_VALUE(access_ctrl, pf_access);
+    SHOW_VALUE(access_ctrl, cache_csr_access);
+    SHOW_VALUE(access_ctrl, pma_csr_access);
+}
+
+/* Convert to human readable size */
+static char *cvt_size(uint32_t size)
+{
+    static char buf[32];
+    char units[] = {'B', 'K', 'M', 'G'};
+    int i = 0;
+    while (size >= 1024 && i < 3) {
+        size >>= 10;
+        i++;
+    }
+    sprintf(buf, "%u %c%s", size, units[i], i > 0 ? "B" : "");
+    return buf;
+}
+
+static void show_cache_info(uint32_t set, uint32_t way, uint32_t lsize,
+                            uint32_t ecc)
+{
+    CIF_PRINTF(" %s", cvt_size(set * way * lsize));
+    CIF_PRINTF("(set=%d,", set);
+    CIF_PRINTF("way=%d,", way);
+    CIF_PRINTF("lsize=%d,", lsize);
+    CIF_PRINTF("ecc=%d)\r\n", !!ecc);
+}

+ 641 - 0
application/baremetal/cpuinfo/cpuinfo.h

@@ -0,0 +1,641 @@
+#ifndef __CPUINFO_H__
+#define __CPUINFO_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+
+/* NOTE: You can define your own printf function by define `CIF_PRINTF`
+ * before include this header file. */
+#ifndef CIF_PRINTF
+#include <stdio.h>
+#define CIF_PRINTF(fmt, ...) printf(fmt, ##__VA_ARGS__)
+#endif
+
+/* NOTE: The CSR register length various between 32-bit and 64-bit
+ * but usually the effective data is in the lower 32 bits. So we
+ * use 32-bit data type to represent most of these registers. */
+typedef uint32_t u32_csr_t;
+typedef uint64_t u64_csr_t;
+
+/**
+ * \brief  Union type to access MCFG_INFO CSR register.
+ */
+typedef union {
+    struct {
+        u32_csr_t tee:1;                         /*!< bit: 0 TEE present */
+        u32_csr_t ecc:1;                         /*!< bit: 1 ECC present */
+        u32_csr_t eclic:1;                       /*!< bit: 2 ECLIC present */
+        u32_csr_t plic:1;                        /*!< bit: 3 PLIC present */
+        u32_csr_t fio:1;                         /*!< bit: 4 FIO present */
+        u32_csr_t ppi:1;                         /*!< bit: 5 PPI present */
+        u32_csr_t nice:1;                        /*!< bit: 6 NICE present */
+        u32_csr_t ilm:1;                         /*!< bit: 7 ILM present */
+        u32_csr_t dlm:1;                         /*!< bit: 8 DLM present */
+        u32_csr_t icache:1;                      /*!< bit: 9 ICache present */
+        u32_csr_t dcache:1;                      /*!< bit: 10 DCache present */
+        u32_csr_t smp:1;                         /*!< bit: 11 SMP present */
+        u32_csr_t dsp_n1:1;                      /*!< bit: 12 DSP N1 present */
+        u32_csr_t dsp_n2:1;                      /*!< bit: 13 DSP N2 present */
+        u32_csr_t dsp_n3:1;                      /*!< bit: 14 DSP N3 present */
+        u32_csr_t zc_xlcz:1;                     /*!< bit: 15 Zc or Zc and xlcz extension present */
+        u32_csr_t iregion:1;                     /*!< bit: 16 IREGION present */
+        u32_csr_t vpu_degree:2;                  /*!< bit: 17..18 Indicate the VPU degree of parallel */
+        u32_csr_t sec_mode:1;                    /*!< bit: 19 Smwg extension present */
+        u32_csr_t etrace:1;                      /*!< bit: 20 Etrace present */
+        u32_csr_t safety_mecha:2;                /*!< bit: 21..22 Indicate Core's safety mechanism */
+        u32_csr_t vnice:1;                       /*!< bit: 23 VNICE present */
+        u32_csr_t xlcz:1;                        /*!< bit: 24 XLCZ extension present */
+        u32_csr_t zilsd:1;                       /*!< bit: 25 Zilsd/Zclsd extension present */
+        u32_csr_t sstc:1;                        /*!< bit: 26 SSTC extension present */
+        u32_csr_t :5;                            /*!< bit: 27..31 Reserved */
+    } b;                                         /*!< Structure used for bit access */
+    u32_csr_t d;                                 /*!< Type      used for csr data access */
+} U32_CSR_MCFG_INFO_Type;
+
+/**
+ * \brief  Union type to access MICFG_INFO CSR register.
+ */
+typedef union {
+    struct {
+        u32_csr_t set:4;                         /*!< bit: 0..3 I-Cache sets per way */
+        u32_csr_t way:3;                         /*!< bit: 4..6 I-Cache way */
+        u32_csr_t lsize:3;                       /*!< bit: 7..9 I-Cache line size */
+        u32_csr_t ecc:1;                         /*!< bit: 10   I-Cache ECC support */
+        u32_csr_t :5;                            /*!< bit: 11..15 Reserved */
+        u32_csr_t lm_size:5;                     /*!< bit: 16..20 ILM size, need to be 2^n size */
+        u32_csr_t lm_xonly:1;                    /*!< bit: 21 ILM Execute only permission or Reserved */
+        u32_csr_t lm_ecc:1;                      /*!< bit: 22 ILM ECC support */
+        u32_csr_t :9;                            /*!< bit: 23..31 Reserved */
+    } b;                                         /*!< Structure used for bit access */
+    u32_csr_t d;                                 /*!< Type      used for csr data access */
+} U32_CSR_MICFG_INFO_Type;
+
+/**
+ * \brief  Union type to access MDCFG_INFO CSR register.
+ */
+typedef union {
+    struct {
+        u32_csr_t set:4;                         /*!< bit: 0..3 D-Cache sets per way */
+        u32_csr_t way:3;                         /*!< bit: 4..6 D-Cache way */
+        u32_csr_t lsize:3;                       /*!< bit: 7..9 D-Cache line size */
+        u32_csr_t ecc:1;                         /*!< bit: 10   D-Cache ECC support */
+        u32_csr_t :5;                            /*!< bit: 11..15 Reserved */
+        u32_csr_t lm_size:5;                     /*!< bit: 16..20 DLM size, need to be 2^n size */
+        u32_csr_t lm_ecc:1;                      /*!< bit: 21 DLM ECC present */
+        u32_csr_t :10;                           /*!< bit: 22..31 Reserved */
+    } b;                                         /*!< Structure used for bit access */
+    u32_csr_t d;                                 /*!< Type      used for csr data access */
+} U32_CSR_MDCFG_INFO_Type;
+
+/**
+ * \brief  Union type to access MTLBCFG_INFO CSR register.
+ */
+typedef union {
+    struct {
+        u32_csr_t set:4;                         /*!< bit: 0..3  Main TLB entry per way */
+        u32_csr_t way:3;                         /*!< bit: 4..6  Main TLB ways */
+        u32_csr_t lsize:3;                       /*!< bit: 7..9  Main TLB line size or Reserved */
+        u32_csr_t ecc:1;                         /*!< bit: 10  Main TLB supports ECC or not */
+        u32_csr_t napot:1;                       /*!< bit: 11  TLB supports Svnapot or not */
+        u32_csr_t :4;                            /*!< bit: 12..15  Reserved */
+        u32_csr_t i_size:3;                      /*!< bit: 16..18  ITLB size */
+        u32_csr_t d_size:3;                      /*!< bit: 19..21  DTLB size */
+        u32_csr_t :9;                            /*!< bit: 22..30  Reserved */
+        u32_csr_t mapping:1;                     /*!< bit: 31  TLB mapping type */
+    } b;                                         /*!< Structure used for bit access */
+    struct {
+        u32_csr_t set:4;                         /*!< bit: 0..3  Main TLB entry per way */
+        u32_csr_t way:3;                         /*!< bit: 4..6  Main TLB ways */
+        u32_csr_t lsize:3;                       /*!< bit: 7..9  Main TLB line size or Reserved */
+        u32_csr_t ecc:1;                         /*!< bit: 10  Main TLB supports ECC or not */
+        u32_csr_t napot:1;                       /*!< bit: 11  TLB supports Svnapot or not */
+        u32_csr_t i_size:7;                      /*!< bit: 12..18  ITLB size */
+        u32_csr_t d_size:8;                      /*!< bit: 19..26  DTLB size */
+        u32_csr_t :4;                            /*!< bit: 27..30  Reserved */
+        u32_csr_t mapping:1;                     /*!< bit: 31  mapping type */
+    } nb;                                        /*!< Structure used for bit access */
+    u32_csr_t d;                                 /*!< Type      used for csr data access */
+} U32_CSR_MTLBCFG_INFO_Type;
+
+/**
+ * \brief  Union type to access MARCHID CSR register.
+ */
+typedef union {
+    struct {
+        u32_csr_t last_name:4;                   /*!< bit: 0..3   the last series name */
+        u32_csr_t third_name:4;                  /*!< bit: 4..7   the third series name */
+        u32_csr_t second_name:4;                 /*!< bit: 8..11  the second series name */
+        u32_csr_t first_name:4;                  /*!< bit: 12..15 the first series name */
+        u32_csr_t :16;                           /*!< bit: 16..31 Reserved */
+    } b;                                         /*!< Structure used for bit access */
+    u32_csr_t d;                                 /*!< Type      used for csr data access */
+} U32_CSR_MARCHID_Type;
+
+/**
+ * \brief  Union type to access MIMPID CSR register.
+ */
+typedef union {
+    struct {
+        u32_csr_t last_vernum:8;                 /*!< bit: 0..7   the last version number */
+        u32_csr_t mid_vernum:8;                  /*!< bit: 8..15  the middle version number */
+        u32_csr_t first_vernum:8;                /*!< bit: 16..23 the first version number */
+        u32_csr_t :8;                            /*!< bit: 24..31 Reserved */
+    } b;                                         /*!< Structure used for bit access */
+    u32_csr_t d;                                 /*!< Type      used for csr data access */
+} U32_CSR_MIMPID_Type;
+
+/**
+ * \brief  Union type to access low 26 bits of MISA CSR register.
+ * 
+ */
+typedef union {
+    struct {
+        u32_csr_t A:1;                           /*!< bit: 0  Atomic extension */
+        u32_csr_t B:1;                           /*!< bit: 1  B extension */
+        u32_csr_t C:1;                           /*!< bit: 2  Compressed exteionsion */
+        u32_csr_t D:1;                           /*!< bit: 3  Double-precision floating-point extension */
+        u32_csr_t E:1;                           /*!< bit: 4  RV32E/64E base ISA */
+        u32_csr_t F:1;                           /*!< bit: 5  Single-precision floating-point extension */
+        u32_csr_t G:1;                           /*!< bit: 6  Reserved */
+        u32_csr_t H:1;                           /*!< bit: 7  Hypervisor extension */
+        u32_csr_t I:1;                           /*!< bit: 8  RV32I/64I/128I base ISA */
+        u32_csr_t J:1;                           /*!< bit: 9  Reserved */
+        u32_csr_t K:1;                           /*!< bit: 10 Reserved */
+        u32_csr_t L:1;                           /*!< bit: 11 Reserved */
+        u32_csr_t M:1;                           /*!< bit: 12 Integer Multiply/Divide extension */
+        u32_csr_t N:1;                           /*!< bit: 13 Tentatively reserved for User-Level Interrupts extension */
+        u32_csr_t O:1;                           /*!< bit: 14 Reserved */
+        u32_csr_t P:1;                           /*!< bit: 15 Tentatively reserved for Packed-SIMD extension */
+        u32_csr_t Q:1;                           /*!< bit: 16 Quad-precision floating-point extension */
+        u32_csr_t R:1;                           /*!< bit: 17 Reserved */
+        u32_csr_t S:1;                           /*!< bit: 18 Supervisor mode implemented */
+        u32_csr_t T:1;                           /*!< bit: 19 Reserved */
+        u32_csr_t U:1;                           /*!< bit: 20 User mode implemented */
+        u32_csr_t V:1;                           /*!< bit: 21 Vector extension */
+        u32_csr_t W:1;                           /*!< bit: 22 Reserved */
+        u32_csr_t X:1;                           /*!< bit: 23 Non-standard extension present */
+        u32_csr_t Y:1;                           /*!< bit: 24 Reserved */
+        u32_csr_t Z:1;                           /*!< bit: 25 Reserved */
+        u32_csr_t :6;                            /*!< bit: 26..31 Reserved */
+    } b;                                         /*!< Structure used for bit access */
+    u32_csr_t d;                                 /*!< Type      used for csr data access */
+} U32_CSR_MISA_Type;
+
+/**
+ * \brief  Union type to access MIRGB_INFO CSR register.
+ */
+typedef union {
+    struct {
+        u64_csr_t :1;                            /*!< bit: 0 Reserved */
+        u64_csr_t iregion_size:5;                /*!< bit: 1..5 IREGION size */
+        u64_csr_t :4;                            /*!< bit: 6..9 Reserved */
+        u64_csr_t iregion_base:54;               /*!< bit: 10..63 IREGION base */
+    } b;                                         /*!< Structure used for bit access */
+    u64_csr_t d;                                 /*!< Type      used for csr data access */
+} U64_CSR_MIRGB_INFO_Type;
+
+/**
+ * \brief  Union type to access MPPICFG_INFO CSR register.
+ */
+typedef union {
+    struct {
+        u64_csr_t :1;                            /*!< bit: 0 Reserved */
+        u64_csr_t ppi_size:5;                    /*!< bit: 1..5 PPI size */
+        u64_csr_t :3;                            /*!< bit: 6..8 Reserved */
+        u64_csr_t :1;                            /*!< bit: 9 PPI Enable */
+        u64_csr_t ppi_base:54;                   /*!< bit: 10..63 PPI base */
+    } b;                                         /*!< Structure used for bit access */
+    u64_csr_t d;                                 /*!< Type      used for csr data access */
+} U64_CSR_MPPICFG_INFO_Type;
+
+/**
+ * \brief  Union type to access MFIOCFG_INFO CSR register.
+ */
+typedef union {
+    struct {
+        u64_csr_t :1;                            /*!< bit: 0 Reserved */
+        u64_csr_t fio_size:5;                    /*!< bit: 1..5 FIO size */
+        u64_csr_t :4;                            /*!< bit: 6..9 Reserved */
+        u64_csr_t fio_base:54;                   /*!< bit: 10..63 FIO base */
+    } b;                                         /*!< Structure used for bit access */
+    u64_csr_t d;                                 /*!< Type      used for csr data access */
+} U64_CSR_MFIOCFG_INFO_Type;
+
+/* IREGION INFO Memory-Mapped Register Type*/
+typedef struct {
+    uint32_t mpasize;                            /*!< offset 0x0000 */
+    uint32_t cmo_info;                           /*!< offset 0x0004 */
+    uint32_t sec_base_addr_lo;                   /*!< offset 0x0008 */
+    uint32_t sec_base_addr_hi;                   /*!< offset 0x000C */
+    uint32_t sec_cfg_info;                       /*!< offset 0x0010 */
+    uint32_t reserved0[4];                       /*!< offset 0x0014 */
+    uint32_t mvlm_cfg_lo;                        /*!< offset 0x0024 */
+    uint32_t mvlm_cfg_hi;                        /*!< offset 0x0028 */
+    uint32_t flash_base_addr_lo;                 /*!< offset 0x002C */
+    uint32_t flash_base_addr_hi;                 /*!< offset 0x0030 */
+    uint32_t reserved1[7];                       /*!< offset 0x0034 */
+    uint32_t vpu_cfg_info;                       /*!< offset 0x0050 */
+    uint32_t mem_region0_cfg_lo;                 /*!< offset 0x0054 */
+    uint32_t mem_region0_cfg_hi;                 /*!< offset 0x0058 */
+    uint32_t mem_region1_cfg_lo;                 /*!< offset 0x005c */
+    uint32_t mem_region1_cfg_hi;                 /*!< offset 0x0060 */
+    uint32_t reserved2[3];                       /*!< offset 0x0064 */
+    uint32_t isa_support0;                       /*!< offset 0x0070 */
+    uint32_t isa_support1;                       /*!< offset 0x0074 */
+    uint32_t reserved3[2];                       /*!< offset 0x0078 */
+    uint32_t mcppi_cfg_lo;                       /*!< offset 0x0080 */
+    uint32_t mcppi_cfg_hi;                       /*!< offset 0x0084 */
+    uint32_t reserved4[2];                       /*!< offset 0x0088 */
+    uint32_t performance_cfg0;                   /*!< offset 0x0090 */
+    uint32_t performance_cfg1;                   /*!< offset 0x0094 */
+    uint32_t reserved5[26];                      /*!< offset 0x0098 */
+    uint32_t pfl1dctrl1;                         /*!< offset 0x0100 */
+    uint32_t pfl1dctrl2;                         /*!< offset 0x0104 */
+    uint32_t mergel1dctrl;                       /*!< offset 0x0108 */
+    uint32_t reserved6[2];                       /*!< offset 0x010C */
+    uint32_t access_ctrl;                        /*!< offset 0x0114 */
+    uint32_t reserved7[2];                       /*!< offset 0x0118 */
+    uint32_t pfl1dctrl3;                         /*!< offset 0x0120 */
+    uint32_t pfl1dctrl4;                         /*!< offset 0x0124 */
+    uint32_t pfl1info;                           /*!< offset 0x0128 */
+    uint32_t reserved8[27];                      /*!< offset 0x012C */
+    uint32_t crc_rf0;                            /*!< offset 0x0198 */
+    uint32_t crc_rf1;                            /*!< offset 0x019C */
+    uint32_t crc_fp0;                            /*!< offset 0x01A0 */
+} IINFO_Type;
+
+/**
+ * \brief  CPU CSR bundles
+ */
+typedef struct {
+    U32_CSR_MARCHID_Type marchid;
+    U32_CSR_MIMPID_Type mimpid;
+    U32_CSR_MISA_Type misa;
+    uint32_t mcfg_exist;
+    U32_CSR_MCFG_INFO_Type mcfginfo;
+    U32_CSR_MICFG_INFO_Type micfginfo;
+    U32_CSR_MDCFG_INFO_Type mdcfginfo;
+    U32_CSR_MTLBCFG_INFO_Type mtlbcfginfo;
+    U64_CSR_MIRGB_INFO_Type mirgbinfo;
+    U64_CSR_MPPICFG_INFO_Type mppicfginfo;
+    U64_CSR_MFIOCFG_INFO_Type mfiocfginfo;
+    IINFO_Type *iinfo;                           /*!< IREGION INFO memory pointer */
+} CPU_CSR_Group;
+
+typedef enum {
+    CIF_XLEN_32 = 0, /* 0 */
+    CIF_XLEN_64,     /* 1 */
+    CIF_XLEN_128,    /* 2 */
+    MAX_CIF_XLEN     /* 3 */
+} CIF_XLEN_Type;
+
+/**
+ * \brief  Union type to access SMP_CFG CSR register.
+ */
+typedef union {
+    struct {
+        u32_csr_t cc:1;                          /*!< bit: 0 Cluster Cache present */
+        u32_csr_t smp_core_num:6;                /*!< bit: 1..6 smp core number */
+        u32_csr_t iocp_num:6;                    /*!< bit: 7..12 IO Coherency port number */
+        u32_csr_t pmon_num:6;                    /*!< bit: 13..18 performance monitor number */
+        u32_csr_t :13;                           /*!< bit: 19..31 Reserved 0 */
+    } b;                                         /*!< Structure used for bit access */
+    u32_csr_t d;                                 /*!< Type      used for csr data access */
+} U32_CSR_SMP_CFG_Type;
+
+/**
+ * \brief  Union type to access SMP_CFG CSR register.
+ */
+typedef union {
+    struct {
+        u32_csr_t set:4;                         /*!< bit: 0..3 Cluster cache set number */
+        u32_csr_t way:4;                         /*!< bit: 4..7 Cluster cache way number */
+        u32_csr_t lsize:3;                       /*!< bit: 8..10 Cluster cache line size */
+        u32_csr_t ecc:1;                         /*!< bit: 11   Cluster cache ECC support */
+        u32_csr_t tcycle:3;                      /*!< bit: 12..14 Tag ram access cycle */
+        u32_csr_t dcycle:3;                      /*!< bit: 15..17 Data ram access cycle */
+        u32_csr_t :14;                           /*!< bit: 18..31 Reserved */
+    } b;                                         /*!< Structure used for bit access */
+    u32_csr_t d;                                 /*!< Type      used for csr data access */
+} U32_CSR_CC_CFG_Type;
+
+/**
+ * \brief  Union type to access SMP_CFG CSR register.
+ */
+typedef union {
+    struct {
+        u32_csr_t num_interrupt:13;              /*!< bit: 0..12 interrupt source number */
+        u32_csr_t version:8;                     /*!< bit: 13..20 version number */
+        u32_csr_t clicintctlbits:4;              /*!< bit: 21..24 clicintctl register bit-width */
+        u32_csr_t :7;                            /*!< bit: 25..31 Reserved 0 */
+    } b;                                         /*!< Structure used for bit access */
+    u32_csr_t d;                                 /*!< Type      used for csr data access */
+} U32_CSR_ECLIC_INFO_Type;
+
+/**
+ * \brief Access to the structure of ECLIC Memory Map, which is compatible with TEE.
+ */
+typedef struct {
+    uint8_t cfg;                                 /*!< Offset: 0x000 (R/W)  CLIC configuration register */
+    uint8_t reserved0[3];
+    U32_CSR_ECLIC_INFO_Type info;                /*!< Offset: 0x004 (R/ )  CLIC information register */
+    uint8_t reserved1;
+    uint8_t reserved2;
+    uint8_t reserved3;
+    uint8_t mth;                                 /*!< Offset: 0x00B(R/W)  CLIC machine mode interrupt-level threshold */
+} ECLIC_Type;
+
+
+/**
+ * \brief  Union type to access MVLM_CFG_LO register.
+ */
+typedef union {
+    struct {
+        uint32_t cmo_cfg:1;                      /*!< bit: 0 CMO exist */
+        uint32_t cmo_pft:1;                      /*!< bit: 1 CMO has prefetch */
+        uint32_t cmo_size:4;                     /*!< bit: 2..5 cache block size */
+        uint32_t cbozero_size:4;                 /*!< bit: 6..9 cache block size of cbo.zero */
+        uint32_t vlm_base_lo:22;                 /*!< bit: 10..31 Reserved 0 */
+    } b;                                         /*!< Structure used for bit access */
+    uint32_t d;                                  /*!< Type      used for register data access */
+} IINFO_MCMO_INFO_Type;
+
+/**
+ * \brief  Union type to access MVLM_CFG_LO register.
+ */
+typedef union {
+    struct {
+        uint32_t vlm:1;                          /*!< bit: 0 whether VLM configuration exist */
+        uint32_t vlm_size:5;                     /*!< bit: 1..5 VLM size */
+        uint32_t :4;                             /*!< bit: 6..9 reserved */
+        uint32_t vlm_base_lo:22;                 /*!< bit: 10..31 VLM base address */
+    } b;                                         /*!< Structure used for bit access */
+    uint32_t d;                                  /*!< Type      used for register data access */
+} IINFO_MVLM_CFG_LO_Type;
+
+typedef uint32_t IINFO_MVLM_CFG_HI_Type;
+
+/**
+ * \brief  Union type to access ISA_SUPPORT0 register.
+ */
+typedef union {
+    struct {
+        uint32_t exist:1;                        /*!< bit: 0 whether this register is valid */
+        uint32_t vector:1;                       /*!< bit: 1 support Vector extension */
+        uint32_t vector_b:1;                     /*!< bit: 2 support Vector-B extension */
+        uint32_t vector_k:1;                     /*!< bit: 3 support Vector-K extension */
+        uint32_t smepmp:1;                       /*!< bit: 4 support Smepmp extension */
+        uint32_t sscofpmf:1;                     /*!< bit: 5 support Sscofpmf extension */
+        uint32_t zfh:1;                          /*!< bit: 6 support Zfh extension */
+        uint32_t zfhmin:1;                       /*!< bit: 7 support Zfhmin extension */
+        uint32_t zfa:1;                          /*!< bit: 8 support Zfa extension */
+        uint32_t svnapot:1;                      /*!< bit: 9 support Svnapot extension */
+        uint32_t svpbmt:1;                       /*!< bit: 10 support Svpbmt extension */
+        uint32_t svinval:1;                      /*!< bit: 11 support Svinval extension */
+        uint32_t bf16:1;                         /*!< bit: 12 support Bf16 extension */
+        uint32_t zve32x:1;                       /*!< bit: 13 support Zve32x extension */
+        uint32_t zve32f:1;                       /*!< bit: 14 support Zve32f extension */
+        uint32_t zve64x:1;                       /*!< bit: 15 support Zve64x extension */
+        uint32_t zve64f:1;                       /*!< bit: 16 support Zve64f extension */
+        uint32_t zve64d:1;                       /*!< bit: 17 support Zve64d extension */
+        uint32_t zimop:1;                        /*!< bit: 18 support Zimop extension */
+        uint32_t zcmop:1;                        /*!< bit: 19 support Zomop extension */
+        uint32_t zicond:1;                       /*!< bit: 20 support Zicond extension */
+        uint32_t zihintntl:1;                    /*!< bit: 21 support Zihintntl extension */
+        uint32_t zihintpause:1;                  /*!< bit: 22 support Zihintpause extension */
+        uint32_t zvfh:1;                         /*!< bit: 23 support Zvfh extension */
+        uint32_t zvfhmin:1;                      /*!< bit: 24 support Zvfhmin extension */
+        uint32_t smrnmi:1;                       /*!< bit: 25 support Smrnmi extension */
+        uint32_t zihpm:1;                        /*!< bit: 26 support Zihpm extension */
+        uint32_t smcntrpmf:1;                    /*!< bit: 27 support Smcntrpmf extension */
+        uint32_t zicntr:1;                       /*!< bit: 28 support Zicntr extension */
+        uint32_t zawrs:1;                        /*!< bit: 29 support Zawrs extension */
+        uint32_t :2;
+    } b;                                         /*!< Structure used for bit access */
+    uint32_t d;                                  /*!< Type      used for register data access */
+} IINFO_ISA_SUPPORT0_Type;
+
+/**
+ * \brief  Union type to access ISA_SUPPORT1 register.
+ */
+typedef union {
+    struct {
+        uint32_t exist:1;                        /*!< bit: 0 whether this register is valid */
+        uint32_t ssqosid:1;                      /*!< bit: 1 support Ssqosid extension */
+        uint32_t zicflip:1;                      /*!< bit: 2 support zicflip extension */
+        uint32_t zicfiss:1;                      /*!< bit: 3 support zicfiss extension */
+        uint32_t smctr:1;                        /*!< bit: 4 support Smctr extension */
+        uint32_t zacas:1;                        /*!< bit: 5 support Zacas extension */
+        uint32_t zabha:1;                        /*!< bit: 6 support Zabha extension */
+        uint32_t smdbltrp:1;                     /*!< bit: 7 support Smdbltrp extension */
+        uint32_t ssdbltrp:1;                     /*!< bit: 8 support Ssdbltrp extension */
+        uint32_t smcdeleg:1;                     /*!< bit: 9 support Smcdeleg extension */
+        uint32_t smmpm:1;                        /*!< bit: 10 support Smmpm extension */
+        uint32_t smnpm:1;                        /*!< bit: 11 support Smnpm extension */
+        uint32_t ssnpm:1;                        /*!< bit: 12 support Smnpm extension */
+        uint32_t smstateen:1;                    /*!< bit: 13 support Smstateen extension */
+        uint32_t sstateen:1;                     /*!< bit: 14 support Sstateen extension */
+        uint32_t smcsrind:1;                     /*!< bit: 15 support Smcsrind extension */
+        uint32_t sscsrind:1;                     /*!< bit: 16 support Sscsrind extension */
+        uint32_t svadu:1;                        /*!< bit: 17 support Svadu extension */
+        uint32_t :14;
+    } b;                                         /*!< Structure used for bit access */
+    uint32_t d;                                  /*!< Type      used for register data access */
+} IINFO_ISA_SUPPORT1_Type;
+
+/**
+ * \brief  Union type to access PERFORMANCE_CFG0 register.
+ */
+typedef union {
+    struct {
+        uint32_t exist:1;                        /*!< bit: 0 whether this register is valid */
+        uint32_t fpu_cycle:5;                    /*!< bit: 1..5 fpu cycle count */
+        uint32_t high_div:1;                     /*!< bit: 6 high performance divider */
+        uint32_t dcache_2stage:1;                /*!< bit: 7 dcache 2 stage */
+        uint32_t delay_branch_flush:1;           /*!< bit: 8 delay branch flash */
+        uint32_t bus_type:3;                     /*!< bit: 9..11 memory bus protocol type */
+        uint32_t dual_issue:1;                   /*!< bit: 12 dual issue */
+        uint32_t cross_4k:1;                     /*!< bit: 13 cross 4k */
+        uint32_t dlm_2stage:1;                   /*!< bit: 14 DLM 2 stage */
+        uint32_t lsu_cut_fwd:1;                  /*!< bit: 15 LSU cut forwarding */
+        uint32_t dsp_cycle:4;                    /*!< bit: 16..19 DSP cycle */
+        uint32_t ifu_cut_timing:1;               /*!< bit: 20 IFU cut timing */
+        uint32_t mem_cut_timing:1;               /*!< bit: 21 MEM cut timing */
+        uint32_t dcache_prefetch:1;              /*!< bit: 22 dcache prefetch */
+        uint32_t dcache_lbuf_num:5;              /*!< bit: 23..27 dcache line buffer number */
+        uint32_t mul_cyc:3;                      /*!< bit: 28..30 multiplier cycle */
+        uint32_t :1;
+    } b;                                         /*!< Structure used for bit access */
+    uint32_t d;                                  /*!< Type      used for register data access */
+} IINFO_PERFORMANCE_CFG0_Type;
+
+/**
+ * \brief  Union type to access PERFORMANCE_CFG1 register.
+ */
+typedef union {
+    struct {
+        uint32_t exist:1;                        /*!< bit: 0 whether this register is valid */
+        uint32_t vfpu_cyc:5;                     /*!< bit: 1..5 Vector FPU cycle */
+        uint32_t bht_entry_width:5;              /*!< bit: 6..10 BHT entry width */
+        uint32_t high_performance:1;             /*!< bit: 11 high performance */
+        uint32_t agu_quick_forward:1;            /*!< bit: 12 agu quick forward */
+        uint32_t cau_fwd:1;                      /*!< bit: 13 crypto instruction forward */
+        uint32_t hpm_ver:2;                      /*!< bit: 14..15 HPM version */
+        uint32_t :16;
+    } b;                                         /*!< Structure used for bit access */
+    uint32_t d;                                  /*!< Type      used for register data access */
+} IINFO_PERFORMANCE_CFG1_Type;
+
+/**
+ * \brief  Union type to access PFL1INFO register.
+ */
+typedef union {
+    struct {
+        uint32_t pf_cfg:8;                       /*!< bit: 0..7 prefetch configuration */
+        uint32_t l2_pf_lbuf_num:8;               /*!< bit: 8..15 L2 prefetch req address buf number */
+        uint32_t l2_pf_dbuf_num:8;               /*!< bit: 16..23 L2 prefetch data buf number */
+        uint32_t pf_ver:8;                       /*!< bit: 24..31 prefetch version */
+    } b;                                         /*!< Structure used for bit access */
+    uint32_t d;                                  /*!< Type      used for register data access */
+} IINFO_PFL1INFO_Type;
+
+/**
+ * \brief  Union type to access PFL1DCTRL1 register.
+ */
+typedef union {
+    struct {
+        uint32_t l1d_ena:1;                      /*!< bit: 0 L1 dcache prefetch enable */
+        uint32_t cc_ena:1;                       /*!< bit: 1 cluster cache prefetch enable */
+        uint32_t scalar_ena:1;                   /*!< bit: 2 scalar pipeline prefetch enable */
+        uint32_t vector_ena:1;                   /*!< bit: 3 vector pipeline prefetch enable */
+        uint32_t write_pref_ena:1;               /*!< bit: 4 store prefetch enable */
+        uint32_t cross_page_pref_ena:1;          /*!< bit: 5 prefetch cross page enable */
+        uint32_t :2;                             /*!< bit: 6..7 reserved */
+        uint32_t pref_conflict_stop_th:4;        /*!< bit: 8..11 prefetch inc counter stop threshold */
+        uint32_t pref_conflict_decr_sel:3;       /*!< bit: 12..14 prefetch num to dec counter */
+        uint32_t :16;                            /*!< bit: 15..31 reserved */
+    } b;                                         /*!< Structure used for bit access */
+    uint32_t d;                                  /*!< Type      used for register data access */
+} IINFO_PFL1DCTRL1_Type;
+
+/**
+ * \brief  Union type to access PFL1DCTRL2 register.
+ */
+typedef union {
+    struct {
+        uint32_t degree_incr_th:6;               /*!< bit: 0..5 prefetch degree threshold of incr */
+        uint32_t degree_decr_th:6;               /*!< bit: 6..11 prefetch degree threshold of decr */
+        uint32_t next_line_ena_th:4;             /*!< bit: 12..15 next line enable threshold */
+        uint32_t write_noalloc_l1_th:2;          /*!< bit: 16..17 see ISA doc */
+        uint32_t write_noalloc_l2_th:2;          /*!< bit: 18..19 see ISA doc */
+        uint32_t :12;                            /*!< bit: 20..31 reserved */
+    } b;                                         /*!< Structure used for bit access */
+    uint32_t d;                                  /*!< Type      used for register data access */
+} IINFO_PFL1DCTRL2_Type;
+
+/**
+ * \brief  Union type to access PFL1DCTRL3 register.
+ */
+typedef union {
+    struct {
+        uint32_t max_stream_l1_degree:4;         /*!< bit: 0..3 mat stream prefetch L1 degree */
+        uint32_t :1;                             /*!< bit: 4 reserved */
+        uint32_t max_stream_l2_degree:7;         /*!< bit: 5..11 next line enable threshold */
+        uint32_t :4;                             /*!< bit: 12..15 reserved */
+        uint32_t max_stride_cplx_l1_degree:4;    /*!< bit: 16..19 the max stride/cplx pref L1 degree */
+        uint32_t :1;                             /*!< bit: 20 reserved */
+        uint32_t max_stride_cplx_l2_degree:7;    /*!< bit: 21..27 the max stride/cplx pref L2 degree */
+        uint32_t :4;                             /*!< bit: 28..31 reserved */
+    } b;                                         /*!< Structure used for bit access */
+    uint32_t d;                                  /*!< Type      used for register data access */
+} IINFO_PFL1DCTRL3_Type;
+
+/**
+ * \brief  Union type to access MERGEL1DCTRL register.
+ */
+typedef union {
+    struct {
+        uint32_t ws_tmout_max:12;                /*!< bit: 0..11 write streaming tmout cnt max value */
+        uint32_t :4;                             /*!< bit: 12..15 reserved */
+        uint32_t nc_tmout_max:8;                 /*!< bit: 16..23 non-cacheable tmout cnt max value */
+        uint32_t dev_store_early_ret: 1;         /*!< bit: 24 whether device region store is blocking */
+        uint32_t :7;                             /*!< bit: 25..31 reserved */
+    } b;                                            /*!< Structure used for bit access */
+    uint32_t d;                                  /*!< Type      used for register data access */
+} IINFO_MERGEL1DCTRL_Type;
+
+/**
+ * \brief  Union type to access ACCESS_CTRL register.
+ */
+typedef union {
+    struct {
+        uint32_t :1;                             /*!< bit: 0 reversed */
+        uint32_t pf_access: 1;                   /*!< bit: 1 s-mode register access, 0 is enable */
+        uint32_t cache_csr_access: 1;            /*!< bit: 2 s-mode cache csr access */
+        uint32_t pma_csr_access: 1;              /*!< bit: 3 s-mode pma csr access */
+        uint32_t :28;                            /*!< bit: 4..31 reserved */
+    } b;                                         /*!< Structure used for bit access */
+    uint32_t d;                                  /*!< Type      used for register data access */
+} IINFO_ACCESS_CTRL_Type;
+
+/**
+ * \brief  Union type to access FLASH_BASE_ADDR_LO register.
+ */
+typedef union {
+    struct {
+        uint32_t flash:1;                        /*!< bit: 0 whether flash bus configuration exist */
+        uint32_t flash_size:5;                   /*!< bit: 1..5 flash size */
+        uint32_t :4;                             /*!< bit: 6..9 reserved */
+        uint32_t flash_base_lo:22;               /*!< bit: 10..31 flash base address low */
+    } b;                                         /*!< Structure used for bit access */
+    uint32_t d;                                  /*!< Type      used for register data access */
+} IINFO_FLASH_BASE_ADDR_LO_Type;
+
+typedef uint32_t IINFO_FLASH_BASE_ADDR_HI_Type;
+
+/**
+ * \brief  Union type to access MEM_REGION_CFG_LO register.
+ */
+typedef union {
+    struct {
+        uint32_t exist:1;                        /*!< bit: 0 whether mem_region_cfg exist */
+        uint32_t mem_region_size:5;              /*!< bit: 1..5 mem region size */
+        uint32_t :3;                             /*!< bit: 6..8 reserved */
+        uint32_t mem_region_ena: 1;              /*!< bit: 9 enable mem region or not */
+        uint32_t mem_region_base_lo:22;          /*!< bit: 10..31 mem region base address low */
+    } b;                                         /*!< Structure used for bit access */
+    uint32_t d;                                  /*!< Type      used for register data access */
+} IINFO_MEM_REGION_CFG_LO_Type;
+
+typedef uint32_t IINFO_MEM_REGION_CFG_HI_Type;
+
+/**
+ * \brief  Union type to access MCPPI_CFG_LO register.
+ */
+typedef union {
+    struct {
+        uint32_t exist:1;                        /*!< bit: 0 whether cppi_cfg exist */
+        uint32_t cppi_size:5;                    /*!< bit: 1..5 cppi size */
+        uint32_t :3;                             /*!< bit: 6..8 reserved */
+        uint32_t cppi_ena: 1;                    /*!< bit: 9 enable cppi or not */
+        uint32_t cppi_base_lo:22;                /*!< bit: 10..31 cppi base address low */
+    } b;                                         /*!< Structure used for bit access */
+    uint32_t d;                                  /*!< Type      used for register data access */
+} IINFO_MCPPI_CFG_LO_Type;
+
+typedef uint32_t IINFO_MCPPI_CFG_HI_Type;
+
+/**
+ * \brief Show full CPU information about ISA, ILD/DLM, I/D cache, etc.
+ * \param xlen: XLEN
+ * \param csrs: pointer to CPU_CSR_Group
+ */
+void show_cpuinfo(CIF_XLEN_Type xlen, const CPU_CSR_Group *csrs);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* #ifndef __IREGION_INFO_H__ */

+ 43 - 326
application/baremetal/cpuinfo/main.c

@@ -1,72 +1,11 @@
 #include <stdio.h>
-#include "nuclei_sdk_soc.h"
-
-#define KB                  (1024)
-#define MB                  (KB * 1024)
-#define GB                  (MB * 1024)
-#define EXTENSION_NUM       (26)
-#define POWER_FOR_TWO(n)    (1UL << (n))
-#define LINESZ(n)           ((n) > 0 ? POWER_FOR_TWO((n)-1) : 0)
-
-void show_safety_mechanism(unsigned long safetyMode)
-{
-    switch (safetyMode) {
-        case 0b00: printf(" No-Safety-Mechanism"); break;
-        case 0b01: printf(" Lockstep"); break;
-        case 0b10: printf(" Lockstep+SplitMode"); break;
-        case 0b11: printf(" ASIL-B"); break;
-        default: return;
-    }
-}
-
-void show_vpu_degree(unsigned long degree)
-{
-    switch (degree) {
-        case 0b00: printf(" DLEN=VLEN/2"); break;
-        case 0b01: printf(" DLEN=VLEN"); break;
-        default: return;
-    }
-}
-
-void print_size(unsigned long bytes)
-{
-    if (bytes / GB) {
-        printf(" %ld GB", bytes / GB);
-    } else if (bytes / MB) {
-        printf(" %ld MB", bytes / MB);
-    } else if (bytes / KB) {
-        printf(" %ld KB", bytes / KB);
-    } else {
-        printf(" %ld Byte", bytes);
-    }
-}
+#include <string.h>
 
-void show_cache_info(unsigned long set, unsigned long way, unsigned long lsize, unsigned long ecc)
-{
-    print_size(set * way * lsize);
-    printf("(set=%ld,", set);
-    printf("way=%ld,", way);
-    printf("lsize=%ld,", lsize);
-    printf("ecc=%ld)\r\n", !!ecc);
-}
+#include "cpuinfo.h"
+#include "nuclei_sdk_soc.h"
 
-void nuclei_cpuinfo(void)
+int main(void)
 {
-    CSR_MCFGINFO_Type mcfg;
-    CSR_MICFGINFO_Type micfg;
-    CSR_MDCFGINFO_Type mdcfg;
-    CSR_MTLBCFGINFO_Type mtlbcfg;
-    rv_csr_t iregion_base = 0;
-    rv_csr_t csr_marchid = 0;
-    rv_csr_t csr_mimpid = 0;
-    rv_csr_t csr_misa = 0;
-    rv_csr_t csr_mirgb = 0;
-    rv_csr_t csr_mfiocfg = 0;
-    rv_csr_t csr_mppicfg = 0;
-
-
-    // CFG_CPU_NAME/CFG_CPU_VERSION/CPU_ISA are macros defined in cpufeature.h auto generated by nuclei_gen
-    // nuclei_gen is our cpu ip generation tool
 #ifdef CFG_CPU_NAME
     printf("CPU NAME: %s\n", CFG_CPU_NAME);
 #endif
@@ -77,278 +16,56 @@ void nuclei_cpuinfo(void)
     printf("CPU ISA: %s\n", CPU_ISA);
 #endif
 
-    printf("\r\n-----Nuclei RISC-V CPU Configuration Information-----\r\n");
-
-    /* ID and version */
-    csr_marchid = __RV_CSR_READ(CSR_MARCHID);
-    csr_mimpid = __RV_CSR_READ(CSR_MIMPID);
-    printf("         MARCHID: 0x%lx\r\n", csr_marchid);
-    printf("          MIMPID: 0x%lx\r\n", csr_mimpid);
-
-    /* ISA */
-    csr_misa = __RV_CSR_READ(CSR_MISA);
-    printf("             ISA:");
-#if __RISCV_XLEN == 32
-    printf(" RV32");
-#else
-    printf(" RV64");
-#endif
-    for (int i = 0; i < EXTENSION_NUM; i++) {
-        if (csr_misa & BIT(i)) {
-            if ('X' == ('A' + i)) {
-                printf(" NICE");
-            } else {
-                printf(" %c", 'A' + i);
-            }
-        }
-    }
-    mcfg.d = __RV_CSR_READ(CSR_MCFG_INFO);
-    if (mcfg.b.dsp_n1) {
-        printf(" Xxldspn1x");
-    }
-    if (mcfg.b.dsp_n2) {
-        printf(" Xxldspn2x");
-    }
-    if (mcfg.b.dsp_n3) {
-        printf(" Xxldspn3x");
-    }
-    if (mcfg.b.zc_xlcz) {
-#if __RISCV_XLEN == 32
-        printf(" Zc Xxlcz");
-#else
-        printf(" Zc");
-#endif
-    }
-    if (mcfg.b.sec_mode) {
-        printf(" Smwg");
-    }
-    printf("\r\n");
-
-    /* Support */
-    printf("            MCFG:");
-    if (mcfg.b.tee) {
-        printf(" TEE");
-    }
-    if (mcfg.b.ecc) {
-        printf(" ECC");
-    }
-    if (mcfg.b.clic) {
-        printf(" ECLIC");
-    }
-    if (mcfg.b.plic) {
-        printf(" PLIC");
-    }
-    if (mcfg.b.fio) {
-        printf(" FIO");
-    }
-    if (mcfg.b.ppi) {
-        printf(" PPI");
-    }
-    if (mcfg.b.nice) {
-        printf(" NICE");
-    }
-    if (mcfg.b.ilm) {
-        printf(" ILM");
-    }
-    if (mcfg.b.dlm) {
-        printf(" DLM");
-    }
-    if (mcfg.b.icache) {
-        printf(" ICACHE");
-    }
-    if (mcfg.b.dcache) {
-        printf(" DCACHE");
-    }
-    if (mcfg.b.smp) {
-        printf(" SMP");
-    }
-    if (mcfg.b.dsp_n1) {
-        printf(" DSP_N1");
-    }
-    if (mcfg.b.dsp_n2) {
-        printf(" DSP_N2");
-    }
-    if (mcfg.b.dsp_n3) {
-        printf(" DSP_N3");
-    }
-    if (mcfg.b.zc_xlcz) {
-#if __RISCV_XLEN == 32
-        printf(" ZC_XLCZ_EXT");
-#else
-        printf(" ZC_EXT");
-#endif
-    }
-    if (mcfg.b.iregion) {
-        printf(" IREGION");
-    }
-    if (mcfg.b.sec_mode) {
-        printf(" SEC_MODE");
-    }
-    if (mcfg.b.etrace) {
-        printf(" ETRACE");
-    }
-    if (mcfg.b.vnice) {
-        printf(" VNICE");
-    }
-    show_safety_mechanism(mcfg.b.safety_mecha);
-    if (csr_misa & BIT(21)) {
-        show_vpu_degree(mcfg.b.vpu_degree);
-    }
-    printf("\r\n");
-
-    /* ILM */
-    if (mcfg.b.ilm) {
-        micfg.d = __RV_CSR_READ(CSR_MICFG_INFO);
-        printf("             ILM:");
-        print_size(POWER_FOR_TWO(micfg.b.lm_size - 1) * 256);
-        if (micfg.b.lm_xonly) {
-            printf(" execute-only");
-        }
-        if (micfg.b.lm_ecc) {
-            printf(" has-ecc");
+    CIF_XLEN_Type xlen;
+    CPU_CSR_Group csrs;
+    memset(&csrs, 0, sizeof(csrs)); // clear the struct
+
+    csrs.marchid.d = (uint32_t)__RV_CSR_READ(CSR_MARCHID);
+    csrs.mimpid.d = (uint32_t)__RV_CSR_READ(CSR_MIMPID);
+    csrs.misa.d = (uint32_t)__RV_CSR_READ(CSR_MISA);
+    U32_CSR_MCFG_INFO_Type mcfg;
+    mcfg.d = (uint32_t)__RV_CSR_READ(CSR_MCFG_INFO);
+    csrs.mcfg_exist = 1;
+    csrs.mcfginfo = mcfg; 
+
+    /**
+     * mtlbcfginfo has a `mapping` field at the highest bit.
+     * For RV64, move the bit 63 to bit 31 to use the common
+     * struct as RV32.
+     */
+    if (__RISCV_XLEN == 32) {
+        xlen = CIF_XLEN_32;
+        if (mcfg.b.plic) {
+            csrs.mtlbcfginfo.d = (uint32_t)__RV_CSR_READ(CSR_MTLBCFG_INFO);
         }
-        printf("\r\n");
-    }
-
-    /* DLM */
-    if (mcfg.b.dlm) {
-        mdcfg.d = __RV_CSR_READ(CSR_MDCFG_INFO);
-        printf("             DLM:");
-        print_size(POWER_FOR_TWO(mdcfg.b.lm_size - 1) * 256);
-        if (mdcfg.b.lm_ecc) {
-            printf(" has-ecc");
+    } else {
+        xlen = CIF_XLEN_64;
+        if (mcfg.b.plic) {
+            uint64_t mtlbcfginfo = __RV_CSR_READ(CSR_MTLBCFG_INFO);
+            csrs.mtlbcfginfo.d =
+                (uint32_t)mtlbcfginfo | (uint32_t)((mtlbcfginfo >> 63) << 31);
         }
-        printf("\r\n");
     }
 
-    /* ICACHE */
-    if (mcfg.b.icache) {
-        micfg.d = __RV_CSR_READ(CSR_MICFG_INFO);
-        printf("          ICACHE:");
-        show_cache_info(POWER_FOR_TWO(micfg.b.set + 3), micfg.b.way + 1, POWER_FOR_TWO(micfg.b.lsize + 2), mcfg.b.ecc);
+    if (mcfg.b.icache || mcfg.b.ilm) {
+        csrs.micfginfo.d = (uint32_t)__RV_CSR_READ(CSR_MICFG_INFO);
     }
-
-    /* DCACHE */
-    if (mcfg.b.dcache) {
-        mdcfg.d = __RV_CSR_READ(CSR_MDCFG_INFO);
-        printf("          DCACHE:");
-        show_cache_info(POWER_FOR_TWO(mdcfg.b.set + 3), mdcfg.b.way + 1, POWER_FOR_TWO(mdcfg.b.lsize + 2), mcfg.b.ecc);
-    }
-
-    /* TLB only present with MMU, when PLIC present MMU will present */
-    if (mcfg.b.plic) {
-        mtlbcfg.d = __RV_CSR_READ(CSR_MTLBCFG_INFO);
-        printf("             TLB:");
-        printf(" MainTLB(set=%lu,way=%lu,entry=%lu,ecc=%lu) ITLB(entry=%lu) DTLB(entry=%lu)\r\n", \
-                POWER_FOR_TWO(mtlbcfg.b.set + 3), mtlbcfg.b.way + 1, LINESZ(mtlbcfg.b.lsize), \
-                mtlbcfg.b.ecc, LINESZ(mtlbcfg.b.i_size), LINESZ(mtlbcfg.b.d_size));
+    if (mcfg.b.dcache || mcfg.b.dlm) {
+        csrs.mdcfginfo.d = (uint32_t)__RV_CSR_READ(CSR_MDCFG_INFO);
     }
-
-
-    /* IREGION */
     if (mcfg.b.iregion) {
-        rv_csr_t csr_mirgb = __RV_CSR_READ(CSR_MIRGB_INFO);
-        printf("         IREGION:");
-        iregion_base = csr_mirgb & (~0x3FF);
-        printf(" %#lx", iregion_base);
-        print_size(POWER_FOR_TWO(__RV_EXTRACT_FIELD(csr_mirgb, 0x3F << 1) - 1) * KB);
-        printf("\r\n");
-        printf("                  Unit        Size        Address\r\n");
-        printf("                  INFO        64KB        %#lx\r\n", iregion_base + IREGION_IINFO_OFS);
-        printf("                  DEBUG       64KB        %#lx\r\n", iregion_base + IREGION_DEBUG_OFS);
-        if (mcfg.b.clic) {
-            printf("                  ECLIC       64KB        %#lx\r\n", iregion_base + IREGION_ECLIC_OFS);
-        }
-        printf("                  TIMER       64KB        %#lx\r\n", iregion_base + IREGION_TIMER_OFS);
-        if (mcfg.b.smp) {
-            printf("                  SMP         64KB        %#lx\r\n", iregion_base + IREGION_SMP_OFS);
-        }
-        rv_csr_t smp_cfg = *(rv_csr_t*)(iregion_base + 0x40004);
-        if (mcfg.b.clic && (__RV_EXTRACT_FIELD(smp_cfg, 0x1F << 1) >= 1)) {
-            printf("                  CIDU        64KB        %#lx\r\n", iregion_base + IREGION_IDU_OFS);
-        }
-        if (mcfg.b.plic) {
-            printf("                  PLIC        64MB        %#lx\r\n", iregion_base + IREGION_PLIC_OFS);
-        }
-        /* SMP */
-        if (mcfg.b.smp) {
-            printf("         SMP_CFG:");
-            printf(" CC_PRESENT=%ld", __RV_EXTRACT_FIELD(smp_cfg, 0x1));
-            printf(" SMP_NUM=%ld", __RV_EXTRACT_FIELD(smp_cfg, 0x3F << 1) + 1);
-            printf(" IOCP_NUM=%ld", __RV_EXTRACT_FIELD(smp_cfg, 0x3F << 7));
-            printf(" PMON_NUM=%ld", __RV_EXTRACT_FIELD(smp_cfg, 0x3F << 13));
-            printf("\r\n");
-        }
-        /* ECLIC */
-#if defined(__ECLIC_PRESENT) && (__ECLIC_PRESENT == 1)
-        if (mcfg.b.clic) {
-            printf("           ECLIC:");
-            printf(" VERSION=0x%x", (unsigned int)ECLIC_GetInfoVer());
-            printf(" NUM_INTERRUPT=%u", (unsigned int)ECLIC_GetInfoNum());
-            printf(" CLICINTCTLBITS=%u", (unsigned int)ECLIC_GetInfoCtlbits());
-            printf(" MTH=%u", (unsigned int)ECLIC_GetMth());
-            printf(" NLBITS=%u", (unsigned int)ECLIC_GetCfgNlbits());
-            printf("\r\n");
-        }
-#endif
-
-        /* L2CACHE */
-        if (smp_cfg & BIT(0)) {
-            uint32_t cc_cfg = *(uint32_t *)(iregion_base + 0x40008);
-            printf("         L2CACHE:");
-            show_cache_info(POWER_FOR_TWO(__RV_EXTRACT_FIELD(cc_cfg, 0xF)), __RV_EXTRACT_FIELD(cc_cfg, 0xf << 4) + 1,
-                            POWER_FOR_TWO(__RV_EXTRACT_FIELD(cc_cfg, 0x7 << 8) + 2), cc_cfg & BIT(11));
-        }
-
-        /* INFO */
-        printf("     INFO-Detail:\r\n");
-        uint32_t mpasize = *(uint32_t *)(iregion_base);
-        printf("                  mpasize : %u\r\n", mpasize);
-        uint32_t cmo_info = *(uint32_t*)(iregion_base + 4);
-        if (cmo_info & BIT(0)) {
-            printf("                  cbozero : %uByte\r\n", (unsigned int)POWER_FOR_TWO(__RV_EXTRACT_FIELD(cmo_info, 0xF << 6) + 2));
-            printf("                  cmo     : %uByte\r\n", (unsigned int)POWER_FOR_TWO(__RV_EXTRACT_FIELD(cmo_info, 0xF << 2) + 2));
-            if (cmo_info & BIT(1)) {
-                printf("                  has_prefecth\r\n");
-            }
-        }
-        uint32_t mcppi_cfg_lo = *(uint32_t *)(iregion_base + 0x80);
-        uint32_t mcppi_cfg_hi = *(uint32_t *)(iregion_base + 0x84);
-        if (mcppi_cfg_lo & 0x1) {
-#if __RISCV_XLEN == 32
-            printf("                  cppi    : %#lx", mcppi_cfg_lo & (~0x3FF));
-#else
-            printf("                  cppi    : %#lx", ((uint64_t)mcppi_cfg_hi << 32) | (mcppi_cfg_lo & (~0x3FF)));
-#endif
-            print_size(POWER_FOR_TWO(__RV_EXTRACT_FIELD(mcppi_cfg_lo, 0x1F << 1) - 1) * KB);
-            printf("\r\n");
-        }
-    }
-
-    /* FIO */
-    if (mcfg.b.fio) {
-        csr_mfiocfg = __RV_CSR_READ(CSR_MFIOCFG_INFO);
-        printf("             FIO:");
-        printf(" %#lx", csr_mfiocfg & (~0x3FF));
-        print_size(POWER_FOR_TWO(__RV_EXTRACT_FIELD(csr_mfiocfg, 0x1F << 1) - 1) * KB);
-        printf("\r\n");
+        csrs.mirgbinfo.d = (uint64_t)__RV_CSR_READ(CSR_MIRGB_INFO);
+        unsigned long iregion_base = csrs.mirgbinfo.d & (~0x3FF);
+        csrs.iinfo = (IINFO_Type *)iregion_base;
     }
-
-    /* PPI */
     if (mcfg.b.ppi) {
-        csr_mppicfg = __RV_CSR_READ(CSR_MPPICFG_INFO);
-        printf("             PPI:");
-        printf(" %#lx", csr_mppicfg & (~0x3FF));
-        print_size(POWER_FOR_TWO(__RV_EXTRACT_FIELD(csr_mppicfg, 0x1F << 1) - 1) * KB);
-        printf("\r\n");
+        csrs.mppicfginfo.d = (uint64_t)__RV_CSR_READ(CSR_MPPICFG_INFO);
+    }
+    if (mcfg.b.fio) {
+        csrs.mfiocfginfo.d = (uint64_t)__RV_CSR_READ(CSR_MFIOCFG_INFO);
     }
 
-    printf("-----End of Nuclei CPU INFO-----\r\n");
-}
-
-int main(void)
-{
-    nuclei_cpuinfo();
+    show_cpuinfo(xlen, &csrs);
 
     return 0;
 }