cpu/cva6/core: Cleanup/Simplify integration.
- Cosmetic changes and increase similarities with other CPUs. - Simplification. - Allow converting AXI to Wishbone or AXI-Lite (Still keep wishbone as default). - Connect reset from SoC. - Reorder AXI signals by channels. - Move JTAG integration to add_jtag method.
This commit is contained in:
parent
69451fad09
commit
808f29ed2e
|
@ -2,18 +2,17 @@
|
||||||
# This file is part of LiteX.
|
# This file is part of LiteX.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2021 Hensoldt Cyber GmbH <www.hensoldt-cyber.com>
|
# Copyright (c) 2021 Hensoldt Cyber GmbH <www.hensoldt-cyber.com>
|
||||||
|
# Copyright (c) 2022 Florent Kermarrec <florent@enjoy-digital.fr>
|
||||||
# SPDX-License-Identifier: BSD-2-Clause
|
# SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
|
||||||
from migen import *
|
from migen import *
|
||||||
from migen.fhdl.specials import Tristate
|
|
||||||
|
|
||||||
from litex import get_data_mod
|
from litex import get_data_mod
|
||||||
from litex.soc.interconnect import axi
|
from litex.soc.interconnect import axi
|
||||||
from litex.soc.interconnect import wishbone, stream
|
from litex.soc.interconnect import wishbone
|
||||||
from litex.soc.interconnect.csr import *
|
|
||||||
from litex.soc.cores.cpu import CPU, CPU_GCC_TRIPLE_RISCV64
|
from litex.soc.cores.cpu import CPU, CPU_GCC_TRIPLE_RISCV64
|
||||||
|
|
||||||
class Open(Signal): pass
|
class Open(Signal): pass
|
||||||
|
@ -32,14 +31,13 @@ GCC_FLAGS = {
|
||||||
# ||||/--- Single-Precision Floating-Point
|
# ||||/--- Single-Precision Floating-Point
|
||||||
# |||||/-- Double-Precision Floating-Point
|
# |||||/-- Double-Precision Floating-Point
|
||||||
# imacfd
|
# imacfd
|
||||||
"standard": "-march=rv64imac -mabi=lp64 ",
|
"standard": "-march=rv64imac -mabi=lp64 ",
|
||||||
"full": "-march=rv64gc -mabi=lp64 ",
|
"full": "-march=rv64gc -mabi=lp64 ",
|
||||||
}
|
}
|
||||||
|
|
||||||
# Helpers ------------------------------------------------------------------------------------------
|
# Helpers ------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
def add_manifest_sources(platform, manifest):
|
def add_manifest_sources(platform, manifest):
|
||||||
# TODO: create a pythondata-cpu-cva6 package to be installed with litex, then use this generic comment
|
|
||||||
basedir = get_data_mod("cpu", "cva6").data_location
|
basedir = get_data_mod("cpu", "cva6").data_location
|
||||||
with open(os.path.join(basedir, manifest), 'r') as f:
|
with open(os.path.join(basedir, manifest), 'r') as f:
|
||||||
for l in f:
|
for l in f:
|
||||||
|
@ -50,7 +48,7 @@ def add_manifest_sources(platform, manifest):
|
||||||
else:
|
else:
|
||||||
platform.add_source(os.path.join(basedir, res.group(1)))
|
platform.add_source(os.path.join(basedir, res.group(1)))
|
||||||
|
|
||||||
# CVA6 -----------------------------------------------------------------------------------------
|
# CVA6 ---------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
class CVA6(CPU):
|
class CVA6(CPU):
|
||||||
family = "riscv"
|
family = "riscv"
|
||||||
|
@ -64,8 +62,6 @@ class CVA6(CPU):
|
||||||
nop = "nop"
|
nop = "nop"
|
||||||
io_regions = {0x80000000: 0x80000000} # Origin, Length.
|
io_regions = {0x80000000: 0x80000000} # Origin, Length.
|
||||||
|
|
||||||
has_fpu = ["full"]
|
|
||||||
|
|
||||||
# GCC Flags.
|
# GCC Flags.
|
||||||
@property
|
@property
|
||||||
def gcc_flags(self):
|
def gcc_flags(self):
|
||||||
|
@ -78,114 +74,118 @@ class CVA6(CPU):
|
||||||
@property
|
@property
|
||||||
def mem_map(self):
|
def mem_map(self):
|
||||||
return {
|
return {
|
||||||
"rom" : 0x10000000,
|
"rom" : 0x10000000,
|
||||||
"sram" : 0x20000000,
|
"sram" : 0x20000000,
|
||||||
"csr" : 0x80000000
|
"csr" : 0x80000000
|
||||||
}
|
}
|
||||||
|
|
||||||
jtag_layout = [
|
def __init__(self, platform, variant="standard", use_wishbone=True):
|
||||||
("tck", 1),
|
|
||||||
("tms", 1),
|
|
||||||
("trst", 1),
|
|
||||||
("tdi", 1),
|
|
||||||
("tdo", 1),
|
|
||||||
]
|
|
||||||
|
|
||||||
def __init__(self, platform, variant="standard"):
|
|
||||||
self.platform = platform
|
self.platform = platform
|
||||||
self.variant = variant
|
self.variant = variant
|
||||||
|
|
||||||
data_width = 64
|
|
||||||
self.axi_if = axi_if = axi.AXIInterface(data_width=data_width, address_width=data_width, id_width=4)
|
|
||||||
|
|
||||||
wb_if = wishbone.Interface(data_width=data_width, adr_width=data_width-log2_int(data_width//8))
|
|
||||||
a2w = axi.AXI2Wishbone(axi_if, wb_if, base_address=0x00000000)
|
|
||||||
self.submodules += a2w
|
|
||||||
|
|
||||||
self.memory_buses = []
|
|
||||||
self.periph_buses = [wb_if]
|
|
||||||
|
|
||||||
self.interrupt = Signal(32)
|
|
||||||
self.reset = Signal()
|
self.reset = Signal()
|
||||||
|
self.interrupt = Signal(32)
|
||||||
|
if use_wishbone:
|
||||||
|
self.wb_if = wishbone.Interface(data_width=64, adr_width=29)
|
||||||
|
self.periph_buses = [self.wb_if] # Peripheral buses (Connected to main SoC's bus).
|
||||||
|
else:
|
||||||
|
self.axi_lite_if = axi.AXILiteInterface(data_width=64, address_width=32)
|
||||||
|
self.periph_buses = [self.axi_lite_if] # Peripheral buses (Connected to main SoC's bus).
|
||||||
|
self.memory_buses = [] # Memory buses (Connected directly to LiteDRAM).
|
||||||
|
|
||||||
tdo_i = Signal()
|
# # #
|
||||||
tdo_o = Signal()
|
|
||||||
tdo_oe = Signal()
|
|
||||||
|
|
||||||
pads = Record(self.jtag_layout)
|
# AXI <-> Wishbone/AXILite conversion.
|
||||||
self.pads = pads
|
axi_if = axi.AXIInterface(data_width=64, address_width=32, id_width=4)
|
||||||
self.specials += Tristate(pads.tdo, tdo_o, tdo_oe, tdo_i)
|
if use_wishbone:
|
||||||
|
self.submodules += axi.AXI2Wishbone(axi_if, self.wb_if)
|
||||||
|
else:
|
||||||
|
self.submodules += axi.AXI2AXILite(axi_if, self.axi_lite_if)
|
||||||
|
|
||||||
|
# CPU Instance.
|
||||||
self.cpu_params = dict(
|
self.cpu_params = dict(
|
||||||
# Clk / Rst.
|
# Clk / Rst.
|
||||||
i_clk_i = ClockSignal("sys"),
|
i_clk_i = ClockSignal("sys"),
|
||||||
i_rst_n = ~ResetSignal("sys"),
|
i_rst_n = ~ResetSignal("sys") | self.reset,
|
||||||
|
|
||||||
# Interrupts
|
# Interrupts.
|
||||||
i_irq_sources = self.interrupt,
|
i_irq_sources = self.interrupt,
|
||||||
|
|
||||||
# AXI interface
|
# AXI interface.
|
||||||
o_AWID_o = axi_if.aw.id,
|
o_AWVALID_o = axi_if.aw.valid,
|
||||||
o_AWADDR_o = axi_if.aw.addr,
|
i_AWREADY_i = axi_if.aw.ready,
|
||||||
o_AWLEN_o = axi_if.aw.len,
|
o_AWID_o = axi_if.aw.id,
|
||||||
o_AWSIZE_o = axi_if.aw.size,
|
o_AWADDR_o = axi_if.aw.addr,
|
||||||
o_AWBURST_o = axi_if.aw.burst,
|
o_AWLEN_o = axi_if.aw.len,
|
||||||
o_AWLOCK_o = axi_if.aw.lock,
|
o_AWSIZE_o = axi_if.aw.size,
|
||||||
o_AWCACHE_o = axi_if.aw.cache,
|
o_AWBURST_o = axi_if.aw.burst,
|
||||||
o_AWPROT_o = axi_if.aw.prot,
|
o_AWLOCK_o = axi_if.aw.lock,
|
||||||
o_AWQOS_o = axi_if.aw.qos,
|
o_AWCACHE_o = axi_if.aw.cache,
|
||||||
o_AWREGION_o = Open(),
|
o_AWPROT_o = axi_if.aw.prot,
|
||||||
o_AWUSER_o = Open(),
|
o_AWQOS_o = axi_if.aw.qos,
|
||||||
o_AWVALID_o = axi_if.aw.valid,
|
o_AWREGION_o = Open(),
|
||||||
o_WDATA_o = axi_if.w.data,
|
o_AWUSER_o = Open(),
|
||||||
o_WSTRB_o = axi_if.w.strb,
|
|
||||||
o_WLAST_o = axi_if.w.last,
|
|
||||||
o_WUSER_o = Open(),
|
|
||||||
o_WVALID_o = axi_if.w.valid,
|
|
||||||
o_BREADY_o = axi_if.b.ready,
|
|
||||||
o_ARID_o = axi_if.ar.id,
|
|
||||||
o_ARADDR_o = axi_if.ar.addr,
|
|
||||||
o_ARLEN_o = axi_if.ar.len,
|
|
||||||
o_ARSIZE_o = axi_if.ar.size,
|
|
||||||
o_ARBURST_o = axi_if.ar.burst,
|
|
||||||
o_ARLOCK_o = axi_if.ar.lock,
|
|
||||||
o_ARCACHE_o = axi_if.ar.cache,
|
|
||||||
o_ARPROT_o = axi_if.ar.prot,
|
|
||||||
o_ARQOS_o = axi_if.ar.qos,
|
|
||||||
o_ARUSER_o = Open(),
|
|
||||||
o_ARREGION_o = Open(),
|
|
||||||
o_ARVALID_o = axi_if.ar.valid,
|
|
||||||
o_RREADY_o = axi_if.r.ready,
|
|
||||||
|
|
||||||
i_AWREADY_i = axi_if.aw.ready,
|
o_WVALID_o = axi_if.w.valid,
|
||||||
i_ARREADY_i = axi_if.ar.ready,
|
i_WREADY_i = axi_if.w.ready,
|
||||||
i_WREADY_i = axi_if.w.ready,
|
o_WDATA_o = axi_if.w.data,
|
||||||
i_BVALID_i = axi_if.b.valid,
|
o_WSTRB_o = axi_if.w.strb,
|
||||||
i_BID_i = axi_if.b.id,
|
o_WLAST_o = axi_if.w.last,
|
||||||
i_BRESP_i = axi_if.b.resp,
|
o_WUSER_o = Open(),
|
||||||
i_BUSER_i = 0,
|
|
||||||
i_RVALID_i = axi_if.r.valid,
|
|
||||||
i_RID_i = axi_if.r.id,
|
|
||||||
i_RDATA_i = axi_if.r.data,
|
|
||||||
i_RRESP_i = axi_if.r.resp,
|
|
||||||
i_RLAST_i = axi_if.r.last,
|
|
||||||
i_RUSER_i = 0,
|
|
||||||
|
|
||||||
# JTAG.
|
i_BVALID_i = axi_if.b.valid,
|
||||||
i_trst_n = pads.trst,
|
o_BREADY_o = axi_if.b.ready,
|
||||||
i_tck = pads.tck,
|
i_BID_i = axi_if.b.id,
|
||||||
i_tms = pads.tms,
|
i_BRESP_i = axi_if.b.resp,
|
||||||
i_tdi = pads.tdi,
|
i_BUSER_i = 0,
|
||||||
o_tdo = tdo_o,
|
|
||||||
o_tdo_oe = tdo_oe,
|
|
||||||
|
|
||||||
# TODO: add trace interface
|
o_ARVALID_o = axi_if.ar.valid,
|
||||||
|
i_ARREADY_i = axi_if.ar.ready,
|
||||||
|
o_ARID_o = axi_if.ar.id,
|
||||||
|
o_ARADDR_o = axi_if.ar.addr,
|
||||||
|
o_ARLEN_o = axi_if.ar.len,
|
||||||
|
o_ARSIZE_o = axi_if.ar.size,
|
||||||
|
o_ARBURST_o = axi_if.ar.burst,
|
||||||
|
o_ARLOCK_o = axi_if.ar.lock,
|
||||||
|
o_ARCACHE_o = axi_if.ar.cache,
|
||||||
|
o_ARPROT_o = axi_if.ar.prot,
|
||||||
|
o_ARQOS_o = axi_if.ar.qos,
|
||||||
|
o_ARUSER_o = Open(),
|
||||||
|
o_ARREGION_o = Open(),
|
||||||
|
|
||||||
|
i_RVALID_i = axi_if.r.valid,
|
||||||
|
o_RREADY_o = axi_if.r.ready,
|
||||||
|
i_RID_i = axi_if.r.id,
|
||||||
|
i_RDATA_i = axi_if.r.data,
|
||||||
|
i_RRESP_i = axi_if.r.resp,
|
||||||
|
i_RLAST_i = axi_if.r.last,
|
||||||
|
i_RUSER_i = 0,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Add Verilog sources.
|
# Add Verilog sources.
|
||||||
# TODO: use Flist.cv64a6_imafdc_sv39 and Flist.cv32a6_imac_sv0 instead
|
# TODO: use Flist.cv64a6_imafdc_sv39 and Flist.cv32a6_imac_sv0 instead
|
||||||
add_manifest_sources(platform, 'Flist.cv64a6_imafdc_sv39')
|
add_manifest_sources(platform, "Flist.cv64a6_imafdc_sv39")
|
||||||
add_manifest_sources(platform, 'Flist.cva6_wrapper')
|
add_manifest_sources(platform, "Flist.cva6_wrapper")
|
||||||
|
|
||||||
|
def add_jtag(pads):
|
||||||
|
from migen.fhdl.specials import Tristate
|
||||||
|
self.jtag_tck = Signal()
|
||||||
|
self.jtag_tms = Signal()
|
||||||
|
self.jtag_trst = Signal()
|
||||||
|
self.jtag_tdi = Signal()
|
||||||
|
self.jtag_tdo = Signal()
|
||||||
|
|
||||||
|
tdo_o = Signal()
|
||||||
|
tdo_oe = Signal()
|
||||||
|
self.specials += Tristate(self.jtag_tdo, tdo_o, tdo_oe)
|
||||||
|
|
||||||
|
self.cpu_params.update(
|
||||||
|
i_trst_n = self.jtag_trst,
|
||||||
|
i_tck = self.jtag_tck,
|
||||||
|
i_tms = self.jtag_tms,
|
||||||
|
i_tdi = self.jtag_tdi,
|
||||||
|
o_tdo = tdo_o,
|
||||||
|
o_tdo_oe = tdo_oe,
|
||||||
|
)
|
||||||
|
|
||||||
def set_reset_address(self, reset_address):
|
def set_reset_address(self, reset_address):
|
||||||
self.reset_address = reset_address
|
self.reset_address = reset_address
|
||||||
|
|
Loading…
Reference in New Issue