diff --git a/litex/soc/cores/cpu/cva6/boot-helper.S b/litex/soc/cores/cpu/cva6/boot-helper.S index 657806060..850d8dd25 100644 --- a/litex/soc/cores/cpu/cva6/boot-helper.S +++ b/litex/soc/cores/cpu/cva6/boot-helper.S @@ -4,6 +4,23 @@ .global smp_ap_target .global smp_ap_ready +#if __riscv_xlen == 32 + +boot_helper: + // boot core saves args and jump target for ap cores: + sw a0, smp_ap_args, t1 + sw a1, smp_ap_args+4, t1 + sw a2, smp_ap_args+8, t1 + sw a3, smp_ap_target, t1 + fence w, w + // notify application cores to proceed with boot: + li t0, 1 + sw t0, smp_ap_ready, t1 + // boot core now also ready to boot: + jr a3 + +#else + boot_helper: // boot core saves args and jump target for ap cores: sd a0, smp_ap_args, t1 @@ -16,3 +33,5 @@ boot_helper: sd t0, smp_ap_ready, t1 // boot core now also ready to boot: jr a3 + +#endif diff --git a/litex/soc/cores/cpu/cva6/core.py b/litex/soc/cores/cpu/cva6/core.py index f046c17fd..8150ddc56 100644 --- a/litex/soc/cores/cpu/cva6/core.py +++ b/litex/soc/cores/cpu/cva6/core.py @@ -19,7 +19,7 @@ from litex.soc.cores.cpu import CPU, CPU_GCC_TRIPLE_RISCV64 # Variants ----------------------------------------------------------------------------------------- -CPU_VARIANTS = ["standard", "full"] +CPU_VARIANTS = ["standard", "standard32", "full"] # GCC Flags ---------------------------------------------------------------------------------------- @@ -31,8 +31,9 @@ GCC_FLAGS = { # ||||/--- Single-Precision Floating-Point # |||||/-- Double-Precision Floating-Point # imacfd - "standard": "-march=rv64imac -mabi=lp64 ", - "full": "-march=rv64gc -mabi=lp64 ", + "standard": "-march=rv64imac -mabi=lp64 ", + "standard32": "-march=rv32imac -mabi=ilp32 ", + "full": "-march=rv64gc -mabi=lp64 ", } # Helpers ------------------------------------------------------------------------------------------ @@ -61,13 +62,23 @@ class CVA6(CPU): name = "cva6" human_name = "CVA6" variants = CPU_VARIANTS - data_width = 64 endianness = "little" gcc_triple = CPU_GCC_TRIPLE_RISCV64 - linker_output_format = "elf64-littleriscv" nop = "nop" io_regions = {0x8000_0000: 0x8000_0000} # Origin, Length. + @property + def linker_output_format(self): + return f"elf{self.data_width}-littleriscv" + + @property + def data_width(self): + if self.variant == "standard32": + return 32 + else: + return 64 + + # GCC Flags. @property def gcc_flags(self): @@ -163,8 +174,12 @@ class CVA6(CPU): wrapper_root = os.path.join(os.path.abspath(os.path.dirname(__file__)), "cva6_wrapper") platform.add_source(os.path.join(wrapper_root, "cva6_defines.sv")) # TODO: use Flist.cv64a6_imafdc_sv39 and Flist.cv32a6_imac_sv0 instead + if self.variant == "standard32": + manifest = "Flist.cv32a6_imac_sv32" + else: + manifest = "Flist.cv64a6_imafdc_sv39" add_manifest_sources(platform, os.path.join(get_data_mod("cpu", "cva6").data_location, - "core", "Flist.cv64a6_imafdc_sv39")) + "core", manifest)) # Add wrapper sources add_manifest_sources(platform, os.path.join(wrapper_root, "Flist.cva6_wrapper")) diff --git a/litex/soc/cores/cpu/cva6/crt0.S b/litex/soc/cores/cpu/cva6/crt0.S index 43a861563..75d0a62a3 100644 --- a/litex/soc/cores/cpu/cva6/crt0.S +++ b/litex/soc/cores/cpu/cva6/crt0.S @@ -6,6 +6,128 @@ .global smp_ap_target .global smp_ap_ready +#if __riscv_xlen == 32 + +_start: + j crt_init + nop + nop + nop + nop + nop + nop + nop + +trap_entry: + sw x1, - 1*8(sp) + sw x5, - 2*8(sp) + sw x6, - 3*8(sp) + sw x7, - 4*8(sp) + sw x10, - 5*8(sp) + sw x11, - 6*8(sp) + sw x12, - 7*8(sp) + sw x13, - 8*8(sp) + sw x14, - 9*8(sp) + sw x15, -10*8(sp) + sw x16, -11*8(sp) + sw x17, -12*8(sp) + sw x28, -13*8(sp) + sw x29, -14*8(sp) + sw x30, -15*8(sp) + sw x31, -16*8(sp) + addi sp,sp,-16*8 + call isr + lw x1 , 15*8(sp) + lw x5, 14*8(sp) + lw x6, 13*8(sp) + lw x7, 12*8(sp) + lw x10, 11*8(sp) + lw x11, 10*8(sp) + lw x12, 9*8(sp) + lw x13, 8*8(sp) + lw x14, 7*8(sp) + lw x15, 6*8(sp) + lw x16, 5*8(sp) + lw x17, 4*8(sp) + lw x28, 3*8(sp) + lw x29, 2*8(sp) + lw x30, 1*8(sp) + lw x31, 0*8(sp) + addi sp,sp,16*8 + mret + .text + + +crt_init: + la sp, _fstack + sw zero, smp_ap_ready, t0 + la t0, trap_entry + csrw mtvec, t0 + +smp_select_bp: + csrr a0, mhartid + beqz a0, data_init // hart 0 is bp, everyone else is ap + +smp_ap_loop: + lw t0, smp_ap_ready + beqz t0, smp_ap_loop +smp_ap_boot: + fence r, r + fence.i // i$ flush + lw a0, smp_ap_args // hart ID (but next-stage loads its own) + lw a1, smp_ap_args+4 // DTB pointer (if provded by litex bios) + lw a2, smp_ap_args+8 + lw a3, smp_ap_target + jr a3 +smp_ap_done: + +data_init: + la t0, _fdata + la t1, _edata + la t2, _fdata_rom +data_loop: + beq t0,t1,data_done + lw t3,0(t2) + sw t3,0(t0) + add t0,t0,4 + add t2,t2,4 + j data_loop +data_done: + +bss_init: + la t0, _fbss + la t1, _ebss +bss_loop: + beq t0,t1,bss_done + sw zero,0(t0) + add t0,t0,4 + j bss_loop +bss_done: + + call plic_init // initialize external interrupt controller + li t0, 0x800 // external interrupt sources only (using LiteX timer); + // NOTE: must still enable mstatus.MIE! + csrw mie,t0 + + call main +inf_loop: + j inf_loop + +.bss + .align 4 +smp_ap_args: + .dword 0 + .dword 0 + .dword 0 + .align 4 +smp_ap_target: + .dword 0 + .align 4 +smp_ap_ready: + .dword 0 + +#else + _start: j crt_init nop @@ -123,3 +245,4 @@ smp_ap_target: .align 8 smp_ap_ready: .dword 0 +#endif diff --git a/litex/soc/cores/cpu/cva6/cva6_wrapper/cva6_wrapper.sv b/litex/soc/cores/cpu/cva6/cva6_wrapper/cva6_wrapper.sv index 5f4c19e22..a476ddd78 100644 --- a/litex/soc/cores/cpu/cva6/cva6_wrapper/cva6_wrapper.sv +++ b/litex/soc/cores/cpu/cva6/cva6_wrapper/cva6_wrapper.sv @@ -87,6 +87,13 @@ module cva6_wrapper ( logic [(AxiDataWidth/8)-1:0], logic [ AxiUserWidth-1:0]) +`AXI_TYPEDEF_ALL(axi_dm_slave, + logic [ AxiAddrWidth-1:0], + logic [AxiIdWidthSlaves-1:0], + logic [ riscv::XLEN-1:0], + logic [(riscv::XLEN/8)-1:0], + logic [ AxiUserWidth-1:0]) + AXI_BUS #( .AXI_ADDR_WIDTH ( AxiAddrWidth ), .AXI_DATA_WIDTH ( AxiDataWidth ), @@ -274,93 +281,45 @@ axi2mem #( if (riscv::XLEN==32 ) begin - assign master_to_dm[0].aw_user = '0; - assign master_to_dm[0].w_user = '0; - assign master_to_dm[0].ar_user = '0; + axi_slave_req_t axi_dmi_slv_req; + axi_slave_resp_t axi_dmi_slv_resp; - assign master_to_dm[0].aw_id = dm_axi_m_req.aw.id; - assign master_to_dm[0].ar_id = dm_axi_m_req.ar.id; + axi_dm_slave_req_t axi_dmi_mst_req; + axi_dm_slave_resp_t axi_dmi_mst_resp; + + `AXI_ASSIGN_TO_REQ(axi_dmi_slv_req, master[cva6_wrapper_pkg::Debug]) + `AXI_ASSIGN_FROM_RESP(master[cva6_wrapper_pkg::Debug], axi_dmi_slv_resp) + + `AXI_ASSIGN_FROM_REQ(master_to_dm[0], axi_dmi_mst_req) + `AXI_ASSIGN_TO_RESP(axi_dmi_mst_resp, master_to_dm[0]) assign master[cva6_wrapper_pkg::Debug].r_user ='0; assign master[cva6_wrapper_pkg::Debug].b_user ='0; - xlnx_axi_dwidth_converter_dm_slave i_axi_dwidth_converter_dm_slave( - .s_axi_aclk(clk_i), - .s_axi_aresetn(ndmreset_n), - .s_axi_awid(master[cva6_wrapper_pkg::Debug].aw_id), - .s_axi_awaddr(master[cva6_wrapper_pkg::Debug].aw_addr[31:0]), - .s_axi_awlen(master[cva6_wrapper_pkg::Debug].aw_len), - .s_axi_awsize(master[cva6_wrapper_pkg::Debug].aw_size), - .s_axi_awburst(master[cva6_wrapper_pkg::Debug].aw_burst), - .s_axi_awlock(master[cva6_wrapper_pkg::Debug].aw_lock), - .s_axi_awcache(master[cva6_wrapper_pkg::Debug].aw_cache), - .s_axi_awprot(master[cva6_wrapper_pkg::Debug].aw_prot), - .s_axi_awregion(master[cva6_wrapper_pkg::Debug].aw_region), - .s_axi_awqos(master[cva6_wrapper_pkg::Debug].aw_qos), - .s_axi_awvalid(master[cva6_wrapper_pkg::Debug].aw_valid), - .s_axi_awready(master[cva6_wrapper_pkg::Debug].aw_ready), - .s_axi_wdata(master[cva6_wrapper_pkg::Debug].w_data), - .s_axi_wstrb(master[cva6_wrapper_pkg::Debug].w_strb), - .s_axi_wlast(master[cva6_wrapper_pkg::Debug].w_last), - .s_axi_wvalid(master[cva6_wrapper_pkg::Debug].w_valid), - .s_axi_wready(master[cva6_wrapper_pkg::Debug].w_ready), - .s_axi_bid(master[cva6_wrapper_pkg::Debug].b_id), - .s_axi_bresp(master[cva6_wrapper_pkg::Debug].b_resp), - .s_axi_bvalid(master[cva6_wrapper_pkg::Debug].b_valid), - .s_axi_bready(master[cva6_wrapper_pkg::Debug].b_ready), - .s_axi_arid(master[cva6_wrapper_pkg::Debug].ar_id), - .s_axi_araddr(master[cva6_wrapper_pkg::Debug].ar_addr[31:0]), - .s_axi_arlen(master[cva6_wrapper_pkg::Debug].ar_len), - .s_axi_arsize(master[cva6_wrapper_pkg::Debug].ar_size), - .s_axi_arburst(master[cva6_wrapper_pkg::Debug].ar_burst), - .s_axi_arlock(master[cva6_wrapper_pkg::Debug].ar_lock), - .s_axi_arcache(master[cva6_wrapper_pkg::Debug].ar_cache), - .s_axi_arprot(master[cva6_wrapper_pkg::Debug].ar_prot), - .s_axi_arregion(master[cva6_wrapper_pkg::Debug].ar_region), - .s_axi_arqos(master[cva6_wrapper_pkg::Debug].ar_qos), - .s_axi_arvalid(master[cva6_wrapper_pkg::Debug].ar_valid), - .s_axi_arready(master[cva6_wrapper_pkg::Debug].ar_ready), - .s_axi_rid(master[cva6_wrapper_pkg::Debug].r_id), - .s_axi_rdata(master[cva6_wrapper_pkg::Debug].r_data), - .s_axi_rresp(master[cva6_wrapper_pkg::Debug].r_resp), - .s_axi_rlast(master[cva6_wrapper_pkg::Debug].r_last), - .s_axi_rvalid(master[cva6_wrapper_pkg::Debug].r_valid), - .s_axi_rready(master[cva6_wrapper_pkg::Debug].r_ready), - .m_axi_awaddr(master_to_dm[0].aw_addr), - .m_axi_awlen(master_to_dm[0].aw_len), - .m_axi_awsize(master_to_dm[0].aw_size), - .m_axi_awburst(master_to_dm[0].aw_burst), - .m_axi_awlock(master_to_dm[0].aw_lock), - .m_axi_awcache(master_to_dm[0].aw_cache), - .m_axi_awprot(master_to_dm[0].aw_prot), - .m_axi_awregion(master_to_dm[0].aw_region), - .m_axi_awqos(master_to_dm[0].aw_qos), - .m_axi_awvalid(master_to_dm[0].aw_valid), - .m_axi_awready(master_to_dm[0].aw_ready), - .m_axi_wdata(master_to_dm[0].w_data ), - .m_axi_wstrb(master_to_dm[0].w_strb), - .m_axi_wlast(master_to_dm[0].w_last), - .m_axi_wvalid(master_to_dm[0].w_valid), - .m_axi_wready(master_to_dm[0].w_ready), - .m_axi_bresp(master_to_dm[0].b_resp), - .m_axi_bvalid(master_to_dm[0].b_valid), - .m_axi_bready(master_to_dm[0].b_ready), - .m_axi_araddr(master_to_dm[0].ar_addr), - .m_axi_arlen(master_to_dm[0].ar_len), - .m_axi_arsize(master_to_dm[0].ar_size), - .m_axi_arburst(master_to_dm[0].ar_burst), - .m_axi_arlock(master_to_dm[0].ar_lock), - .m_axi_arcache(master_to_dm[0].ar_cache), - .m_axi_arprot(master_to_dm[0].ar_prot), - .m_axi_arregion(master_to_dm[0].ar_region), - .m_axi_arqos(master_to_dm[0].ar_qos), - .m_axi_arvalid(master_to_dm[0].ar_valid), - .m_axi_arready(master_to_dm[0].ar_ready), - .m_axi_rdata(master_to_dm[0].r_data), - .m_axi_rresp(master_to_dm[0].r_resp), - .m_axi_rlast(master_to_dm[0].r_last), - .m_axi_rvalid(master_to_dm[0].r_valid), - .m_axi_rready(master_to_dm[0].r_ready) + axi_dw_converter #( + .AxiMaxReads(1), + .AxiSlvPortDataWidth(64), + .AxiMstPortDataWidth(32), + .AxiAddrWidth(AxiAddrWidth), + .AxiIdWidth(5), + .aw_chan_t(ariane_axi::aw_chan_t), + .slv_w_chan_t(axi_slave_w_chan_t), + .mst_w_chan_t(axi_dm_slave_w_chan_t), + .b_chan_t(axi_slave_b_chan_t), + .ar_chan_t(axi_slave_ar_chan_t), + .mst_r_chan_t(axi_dm_slave_r_chan_t), + .slv_r_chan_t(axi_slave_r_chan_t), + .axi_slv_req_t(axi_slave_req_t), + .axi_slv_resp_t(axi_slave_resp_t), + .axi_mst_req_t(axi_dm_slave_req_t), + .axi_mst_resp_t(axi_dm_slave_resp_t) + ) i_downsizer_dm_slave ( + .clk_i(clk_i), + .rst_ni(ndmreset_n), + .slv_req_i(axi_dmi_slv_req), + .slv_resp_o(axi_dmi_slv_resp), + .mst_req_o(axi_dmi_mst_req), + .mst_resp_i(axi_dmi_mst_resp) ); end else begin @@ -455,108 +414,8 @@ axi_adapter #( .axi_resp_i ( dm_axi_m_resp ) ); -if (riscv::XLEN==32 ) begin - logic [31 : 0] dm_master_m_awaddr; - logic [31 : 0] dm_master_m_araddr; - - assign slave[1].aw_addr = {32'h0000_0000, dm_master_m_awaddr}; - assign slave[1].ar_addr = {32'h0000_0000, dm_master_m_araddr}; - - logic [31 : 0] dm_master_s_rdata; - - assign dm_axi_m_resp.r.data = {32'h0000_0000, dm_master_s_rdata}; - - assign slave[1].aw_user = '0; - assign slave[1].w_user = '0; - assign slave[1].ar_user = '0; - - assign slave[1].aw_id = dm_axi_m_req.aw.id; - assign slave[1].ar_id = dm_axi_m_req.ar.id; - assign slave[1].aw_atop = dm_axi_m_req.aw.atop; - - xlnx_axi_dwidth_converter_dm_master i_axi_dwidth_converter_dm_master( - .s_axi_aclk(clk_i), - .s_axi_aresetn(ndmreset_n), - .s_axi_awid(dm_axi_m_req.aw.id), - .s_axi_awaddr(dm_axi_m_req.aw.addr[31:0]), - .s_axi_awlen(dm_axi_m_req.aw.len), - .s_axi_awsize(dm_axi_m_req.aw.size), - .s_axi_awburst(dm_axi_m_req.aw.burst), - .s_axi_awlock(dm_axi_m_req.aw.lock), - .s_axi_awcache(dm_axi_m_req.aw.cache), - .s_axi_awprot(dm_axi_m_req.aw.prot), - .s_axi_awregion(dm_axi_m_req.aw.region), - .s_axi_awqos(dm_axi_m_req.aw.qos), - .s_axi_awvalid(dm_axi_m_req.aw_valid), - .s_axi_awready(dm_axi_m_resp.aw_ready), - .s_axi_wdata(dm_axi_m_req.w.data[31:0]), - .s_axi_wstrb(dm_axi_m_req.w.strb[3:0]), - .s_axi_wlast(dm_axi_m_req.w.last), - .s_axi_wvalid(dm_axi_m_req.w_valid), - .s_axi_wready(dm_axi_m_resp.w_ready), - .s_axi_bid(dm_axi_m_resp.b.id), - .s_axi_bresp(dm_axi_m_resp.b.resp), - .s_axi_bvalid(dm_axi_m_resp.b_valid), - .s_axi_bready(dm_axi_m_req.b_ready), - .s_axi_arid(dm_axi_m_req.ar.id), - .s_axi_araddr(dm_axi_m_req.ar.addr[31:0]), - .s_axi_arlen(dm_axi_m_req.ar.len), - .s_axi_arsize(dm_axi_m_req.ar.size), - .s_axi_arburst(dm_axi_m_req.ar.burst), - .s_axi_arlock(dm_axi_m_req.ar.lock), - .s_axi_arcache(dm_axi_m_req.ar.cache), - .s_axi_arprot(dm_axi_m_req.ar.prot), - .s_axi_arregion(dm_axi_m_req.ar.region), - .s_axi_arqos(dm_axi_m_req.ar.qos), - .s_axi_arvalid(dm_axi_m_req.ar_valid), - .s_axi_arready(dm_axi_m_resp.ar_ready), - .s_axi_rid(dm_axi_m_resp.r.id), - .s_axi_rdata(dm_master_s_rdata), - .s_axi_rresp(dm_axi_m_resp.r.resp), - .s_axi_rlast(dm_axi_m_resp.r.last), - .s_axi_rvalid(dm_axi_m_resp.r_valid), - .s_axi_rready(dm_axi_m_req.r_ready), - .m_axi_awaddr(dm_master_m_awaddr), - .m_axi_awlen(slave[1].aw_len), - .m_axi_awsize(slave[1].aw_size), - .m_axi_awburst(slave[1].aw_burst), - .m_axi_awlock(slave[1].aw_lock), - .m_axi_awcache(slave[1].aw_cache), - .m_axi_awprot(slave[1].aw_prot), - .m_axi_awregion(slave[1].aw_region), - .m_axi_awqos(slave[1].aw_qos), - .m_axi_awvalid(slave[1].aw_valid), - .m_axi_awready(slave[1].aw_ready), - .m_axi_wdata(slave[1].w_data ), - .m_axi_wstrb(slave[1].w_strb), - .m_axi_wlast(slave[1].w_last), - .m_axi_wvalid(slave[1].w_valid), - .m_axi_wready(slave[1].w_ready), - .m_axi_bresp(slave[1].b_resp), - .m_axi_bvalid(slave[1].b_valid), - .m_axi_bready(slave[1].b_ready), - .m_axi_araddr(dm_master_m_araddr), - .m_axi_arlen(slave[1].ar_len), - .m_axi_arsize(slave[1].ar_size), - .m_axi_arburst(slave[1].ar_burst), - .m_axi_arlock(slave[1].ar_lock), - .m_axi_arcache(slave[1].ar_cache), - .m_axi_arprot(slave[1].ar_prot), - .m_axi_arregion(slave[1].ar_region), - .m_axi_arqos(slave[1].ar_qos), - .m_axi_arvalid(slave[1].ar_valid), - .m_axi_arready(slave[1].ar_ready), - .m_axi_rdata(slave[1].r_data), - .m_axi_rresp(slave[1].r_resp), - .m_axi_rlast(slave[1].r_last), - .m_axi_rvalid(slave[1].r_valid), - .m_axi_rready(slave[1].r_ready) - ); -end else begin - `AXI_ASSIGN_FROM_REQ(slave[1], dm_axi_m_req) - `AXI_ASSIGN_TO_RESP(dm_axi_m_resp, slave[1]) -end - +`AXI_ASSIGN_FROM_REQ(slave[1], dm_axi_m_req) +`AXI_ASSIGN_TO_RESP(dm_axi_m_resp, slave[1]) // --------------- // Core