Compiles but fails after load!

master
kaqu 2 years ago
parent 5ba92370ba
commit e4f8d5d26c
  1. 44
      debugger/qt5dbg.py
  2. 10
      debugger/risq5dbg.py
  3. 5
      helpers/prepare_firmware.py
  4. 266
      litex/litex/soc/integration/builder.py
  5. 265
      litex/litex/soc/integration/builder.py.original
  6. 188
      litex/litex/soc/integration/soc.py
  7. 2
      litex/litex/soc/integration/soc_core.py
  8. 31
      risq5_wo_vex.py
  9. 8
      software/source/testtimerinterrupt.c

@ -249,20 +249,20 @@ class dbgWindow(QMainWindow):
i32DRAMReadCount, i32DRAMReadOffset, i32DRAMReadData)
self.qpbLUCache.setText(msg)
i32mode = self.wb.regs.risq5_b32mode.read()
i32mode = self.wb.regs.risq5ext_b32mode.read()
msg = "Mode: 0x{:08X} (0000 0000 0".format(i32mode)
msg = msg + flag(i32mode & 64, 'T', '-') + flag(i32mode & 32, 'E', '-') + flag(i32mode & 16, 'P ', '- ')
msg = msg + flag(i32mode & 8, 'B', '-') + flag(i32mode & 4, 'S', '-') + flag(i32mode & 2, 'N', '-') + flag(i32mode & 1, 'R', '-') + ")"
self.qpbMode.setText(msg)
i32status = self.wb.regs.risq5_b32status.read()
i32status = self.wb.regs.risq5ext_b32status.read()
msg = "Status:0x{:08X} (0000 ".format(i32status)
msg = msg + flag(i32status & 2048, 'T', '-') + flag(i32status & 1024, 'E', '-')
msg = msg + flag(i32status & 512, '>', '-') + flag(i32status & 256, '< ', '- ') + flag(i32status & 128,'>', '-') + flag(i32status & 64, '<', '-')
msg = msg + flag(i32status & 32, 'V', '-') + flag(i32status & 16, '>', '-') + " " + flag(i32status & 8, '<', '-') + flag(i32status & 4, 'I', '-') + flag(i32status & 2, 'B', '-') + flag(i32status & 1, 'V', '-') + ")"
self.qpbStatus.setText(msg)
i32FSMs = self.wb.regs.risq5_b32_FSMs.read()
i32FSMs = self.wb.regs.risq5ext_b32_FSMs.read()
msg = "FSMs: 0x{0:08X} (L1={1} ALU={2} LU={3} DECODE={4}) TIMER: mtime={5} mtimecmp={6} SYSTIME:{7}".format(
i32FSMs,
i32FSMs & 0xF,
@ -275,7 +275,7 @@ class dbgWindow(QMainWindow):
)
self.qpbFSMs.setText(msg)
i32Counters = self.wb.regs.risq5_b32_Counters.read()
i32Counters = self.wb.regs.risq5ext_b32_Counters.read()
msg = "CNTs: 0x{0:08X} (C1={1}[L1 loads] C2={2}[Instruction count] C3={3}[L1 offset] C4={4}[LU loads])".format(
i32Counters,
i32Counters & 0xFF,
@ -286,18 +286,18 @@ class dbgWindow(QMainWindow):
self.qpbCNTs.setText(msg)
if bRetrieveAll:
i32Breakpoint = self.wb.regs.risq5_b32_breakpoint.read()
i32Breakpoint = self.wb.regs.risq5ext_b32_breakpoint.read()
self.txtBP.setText("0x{:08X}".format(i32Breakpoint))
i32NextPC = self.wb.regs.risq5_b32_next_pc.read()
i32NextPC = self.wb.regs.risq5ext_b32_next_pc.read()
self.txtNextPC.setText("0x{:08X}".format(i32NextPC))
for i in range(32): # Walk x<n> register file
self.wb.regs.risq5_b5_wb_reg_no.write(i) # Select register
val = self.wb.regs.risq5_b32_wb_reg_value_r.read() # Pick actual register risq5_b32_wb_reg_value_r
self.wb.regs.risq5ext_b5_wb_reg_no.write(i) # Select register
val = self.wb.regs.risq5ext_b32_wb_reg_value_r.read() # Pick actual register risq5_b32_wb_reg_value_r
self.txtList[i].setText("0x{:08X}".format(val))
pc = self.wb.regs.risq5_b32_PC.read()
pc = self.wb.regs.risq5ext_b32_PC.read()
self.txtPC.setText("0x{:08X}".format(pc))
opcode = self.wb.regs.risq5_b32_opcode.read()
opcode = self.wb.regs.risq5ext_b32_opcode.read()
self.txtOpcode.setText("0x{0:08X} {1}".format(opcode, disassemble(opcode, pc)))
@pyqtSlot()
@ -328,13 +328,13 @@ class dbgWindow(QMainWindow):
try:
b32Value = int(sender.text(),16) # Get hex value
#print("x{0} new value: {1}".format(index, b32Value))
self.wb.regs.risq5_b5_wb_reg_no.write(index) # Write index
self.wb.regs.risq5_b32_wb_reg_value_w.write(b32Value) # New value
self.wb.regs.risq5_b1_wb_reg_we.write(1) # Write request (pulse)
self.wb.regs.risq5ext_b5_wb_reg_no.write(index) # Write index
self.wb.regs.risq5ext_b32_wb_reg_value_w.write(b32Value) # New value
self.wb.regs.risq5ext_b1_wb_reg_we.write(1) # Write request (pulse)
time.sleep(0.05) # Just make sure ...
except:
pass
self.wb.regs.risq5_b1_wb_reg_we.write(0) # Write request (pulse)
self.wb.regs.risq5ext_b1_wb_reg_we.write(0) # Write request (pulse)
self.qpbUpdate.setVisible(False)
self.timer.start() # Re-enable timer event
@ -342,7 +342,7 @@ class dbgWindow(QMainWindow):
def on_clickNextStep(self):
self.timer.stop()
#print("*** NEXT STEP ***")
self.wb.regs.risq5_b32mode.write(self.wb.regs.risq5_b32mode.read() | (1 + 4)) # Run enable & trigger single step
self.wb.regs.risq5ext_b32mode.write(self.wb.regs.risq5ext_b32mode.read() | (1 + 4)) # Run enable & trigger single step
self.UpdateRISQ5Stati(True) # THE job
self.timer.start()
@ -350,7 +350,7 @@ class dbgWindow(QMainWindow):
def on_clickExecute(self):
self.timer.stop()
print("*** EXECUTE ***")
self.wb.regs.risq5_b32mode.write(self.wb.regs.risq5_b32mode.read() | (1 + 2)) # Run & 'no single stepping'
self.wb.regs.risq5ext_b32mode.write(self.wb.regs.risq5ext_b32mode.read() | (1 + 2)) # Run & 'no single stepping'
self.UpdateRISQ5Stati(True) # THE job
self.timer.start()
@ -358,7 +358,7 @@ class dbgWindow(QMainWindow):
def on_clickHalt(self):
self.timer.stop()
print("*** HALT ***")
self.wb.regs.risq5_b32mode.write(self.wb.regs.risq5_b32mode.read() & (0xFFFFFFFF - 2)) # Clear 'no signal stepping'
self.wb.regs.risq5ext_b32mode.write(self.wb.regs.risq5ext_b32mode.read() & (0xFFFFFFFF - 2)) # Clear 'no signal stepping'
self.UpdateRISQ5Stati(True) # THE job
self.timer.start()
@ -367,8 +367,8 @@ class dbgWindow(QMainWindow):
self.timer.stop()
print("*** SET BP TO {:08X} ***".format(int(self.txtBP.text(),16)))
i32bp = int(self.txtBP.text(),16) # Pick supplied BP entry
self.wb.regs.risq5_b32_breakpoint.write(i32bp); # and write it to FPGA
self.wb.regs.risq5_b32mode.write(self.wb.regs.risq5_b32mode.read() | 8) # Breakpoint valid now
self.wb.regs.risq5ext_b32_breakpoint.write(i32bp); # and write it to FPGA
self.wb.regs.risq5ext_b32mode.write(self.wb.regs.risq5ext_b32mode.read() | 8) # Breakpoint valid now
self.UpdateRISQ5Stati(True) # THE job
self.timer.start()
@ -377,8 +377,8 @@ class dbgWindow(QMainWindow):
self.timer.stop()
print("*** SET PC TO {:08X} ***".format(int(self.txtNextPC.text(),16)))
i32NextPC = int(self.txtNextPC.text(),16); # Pick supplied PC entry
self.wb.regs.risq5_b32_next_pc.write(i32NextPC) # Provide a new PC address
self.wb.regs.risq5_b32mode.write(self.wb.regs.risq5_b32mode.read() | 16) # Adjust PC now
self.wb.regs.risq5ext_b32_next_pc.write(i32NextPC) # Provide a new PC address
self.wb.regs.risq5ext_b32mode.write(self.wb.regs.risq5ext_b32mode.read() | 16) # Adjust PC now
self.UpdateRISQ5Stati(True) # THE job
self.timer.start()
@ -386,7 +386,7 @@ class dbgWindow(QMainWindow):
def on_clickExtInt(self):
self.timer.stop()
print("*** EXTERNAL INT RAISED ***")
self.wb.regs.risq5_b32mode.write(self.wb.regs.risq5_b32mode.read() | 32) # Trigger external interrupt
self.wb.regs.risq5ext_b32mode.write(self.wb.regs.risq5ext_b32mode.read() | 32) # Trigger external interrupt
self.UpdateRISQ5Stati(True) # THE job
self.timer.start()

@ -25,13 +25,13 @@ def risq5dbg(csr_csv):
print("RISQ5 debugger started ...")
#print("Entering single step mode")
wb.regs.risq5_b32mode.write(1) # Enable run, L1 cache will load (but will halt before 1. instruction!)
wb.regs.risq5ext_b32mode.write(1) # Enable run, L1 cache will load (but will halt before 1. instruction!)
#print("PC adjusted to 0x40190078")
#wb.regs.risq5_b32_next_pc.write(0x40190078) # Provide a new PC address
#mode = wb.regs.risq5_b32mode.read() # Pick up current mode setting
#wb.regs.risq5_b32mode.write(mode | 16) # Adjust PC, will load L1 2nd time now
#wb.regs.risq5_b1_wb_reg_we.write(0) # Reset write requests (if any pending)
#wb.regs.risq5ext_b32_next_pc.write(0x40190078) # Provide a new PC address
#mode = wb.regs.risq5ext_b32mode.read() # Pick up current mode setting
#wb.regs.risq5ext_b32mode.write(mode | 16) # Adjust PC, will load L1 2nd time now
#wb.regs.risq5ext_b1_wb_reg_we.write(0) # Reset write requests (if any pending)
run_Qt5_GUI(wb) # Now switch to GUI (will never return!)

@ -43,6 +43,11 @@ def copyjob():
- standard with IDEs
If run solely from helpers directory will work as well ...
"""
copyjob_actual(
os.path.dirname(litex.soc.integration.__file__) + "/",
os.environ["PWD"] + relpath + "/litex/litex/soc/integration/",
"builder.py"
)
copyjob_actual(
os.path.dirname(litex.soc.integration.__file__) + "/",
os.environ["PWD"] + relpath + "/litex/litex/soc/integration/",

@ -0,0 +1,266 @@
#
# This file is part of LiteX.
#
# This file is Copyright (c) 2015 Sebastien Bourdeauducq <sb@m-labs.hk>
# This file is Copyright (c) 2015-2019 Florent Kermarrec <florent@enjoy-digital.fr>
# This file is Copyright (c) 2018-2019 Antmicro <www.antmicro.com>
# This file is Copyright (c) 2018 Sergiusz Bazanski <q3k@q3k.org>
# This file is Copyright (c) 2016-2017 Tim 'mithro' Ansell <mithro@mithis.com>
# This file is Copyright (c) 2018 William D. Jones <thor0505@comcast.net>
# This file is Copyright (c) 2020 Xiretza <xiretza@xiretza.xyz>
# This file is Copyright (c) 2020 Piotr Esden-Tempski <piotr@esden.net>
# SPDX-License-Identifier: BSD-2-Clause
import os
import subprocess
import struct
import shutil
from litex import get_data_mod
from litex.build.tools import write_to_file
from litex.soc.integration import export, soc_core
from litex.soc.cores import cpu
__all__ = [
"soc_software_packages",
"soc_directory",
"Builder",
"builder_args",
"builder_argdict"
]
soc_software_packages = [
"libcompiler_rt",
"libbase",
"liblitedram",
"libliteeth",
"liblitespi",
"liblitesdcard",
"bios"
]
soc_directory = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
def _makefile_escape(s):
return s.replace("\\", "\\\\")
class Builder:
def __init__(self, soc,
output_dir = None,
gateware_dir = None,
software_dir = None,
include_dir = None,
generated_dir = None,
compile_software = True,
compile_gateware = True,
csr_json = None,
csr_csv = None,
csr_svd = None,
memory_x = None,
bios_options = []):
self.soc = soc
# From Python doc: makedirs() will become confused if the path elements to create include '..'
self.output_dir = os.path.abspath(output_dir or os.path.join("build", soc.platform.name))
self.gateware_dir = os.path.abspath(gateware_dir or os.path.join(self.output_dir, "gateware"))
self.software_dir = os.path.abspath(software_dir or os.path.join(self.output_dir, "software"))
self.include_dir = os.path.abspath(include_dir or os.path.join(self.software_dir, "include"))
self.generated_dir = os.path.abspath(generated_dir or os.path.join(self.include_dir, "generated"))
self.compile_software = compile_software
self.compile_gateware = compile_gateware
self.csr_csv = csr_csv
self.csr_json = csr_json
self.csr_svd = csr_svd
self.memory_x = memory_x
self.bios_options = bios_options
self.software_packages = []
for name in soc_software_packages:
self.add_software_package(name)
def add_software_package(self, name, src_dir=None):
if src_dir is None:
src_dir = os.path.join(soc_directory, "software", name)
self.software_packages.append((name, src_dir))
def _generate_includes(self):
os.makedirs(self.include_dir, exist_ok=True)
os.makedirs(self.generated_dir, exist_ok=True)
if self.soc.cpu_type not in [None, "zynq7000"]:
variables_contents = []
def define(k, v):
variables_contents.append("{}={}\n".format(k, _makefile_escape(v)))
for k, v in export.get_cpu_mak(self.soc.cpu, self.compile_software):
define(k, v)
define(
"COMPILER_RT_DIRECTORY",
get_data_mod("software", "compiler_rt").data_location)
define("SOC_DIRECTORY", soc_directory)
variables_contents.append("export BUILDINC_DIRECTORY\n")
define("BUILDINC_DIRECTORY", self.include_dir)
for name, src_dir in self.software_packages:
define(name.upper() + "_DIRECTORY", src_dir)
for bios_option in self.bios_options:
assert bios_option in ["TERM_NO_HIST", "TERM_MINI", "TERM_NO_COMPLETE"]
define(bios_option, "1")
write_to_file(
os.path.join(self.generated_dir, "variables.mak"),
"".join(variables_contents))
write_to_file(
os.path.join(self.generated_dir, "output_format.ld"),
export.get_linker_output_format(self.soc.cpu))
write_to_file(
os.path.join(self.generated_dir, "regions.ld"),
export.get_linker_regions(self.soc.mem_regions))
write_to_file(
os.path.join(self.generated_dir, "mem.h"),
export.get_mem_header(self.soc.mem_regions))
write_to_file(
os.path.join(self.generated_dir, "soc.h"),
export.get_soc_header(self.soc.constants))
write_to_file(
os.path.join(self.generated_dir, "csr.h"),
export.get_csr_header(
regions = self.soc.csr_regions,
constants = self.soc.constants,
csr_base = self.soc.mem_regions['csr'].origin
)
)
write_to_file(
os.path.join(self.generated_dir, "git.h"),
export.get_git_header()
)
if hasattr(self.soc, "sdram"):
from litedram.init import get_sdram_phy_c_header
write_to_file(os.path.join(self.generated_dir, "sdram_phy.h"),
get_sdram_phy_c_header(
self.soc.sdram.controller.settings.phy,
self.soc.sdram.controller.settings.timing))
def _generate_csr_map(self):
if self.csr_json is not None:
csr_dir = os.path.dirname(os.path.realpath(self.csr_json))
os.makedirs(csr_dir, exist_ok=True)
write_to_file(self.csr_json, export.get_csr_json(self.soc.csr_regions, self.soc.constants, self.soc.mem_regions))
if self.csr_csv is not None:
csr_dir = os.path.dirname(os.path.realpath(self.csr_csv))
os.makedirs(csr_dir, exist_ok=True)
write_to_file(self.csr_csv, export.get_csr_csv(self.soc.csr_regions, self.soc.constants, self.soc.mem_regions))
if self.csr_svd is not None:
svd_dir = os.path.dirname(os.path.realpath(self.csr_svd))
os.makedirs(svd_dir, exist_ok=True)
write_to_file(self.csr_svd, export.get_csr_svd(self.soc))
def _generate_mem_region_map(self):
if self.memory_x is not None:
memory_x_dir = os.path.dirname(os.path.realpath(self.memory_x))
os.makedirs(memory_x_dir, exist_ok=True)
write_to_file(self.memory_x, export.get_memory_x(self.soc))
def _prepare_rom_software(self):
for name, src_dir in self.software_packages:
dst_dir = os.path.join(self.software_dir, name)
os.makedirs(dst_dir, exist_ok=True)
def _generate_rom_software(self, compile_bios=True):
for name, src_dir in self.software_packages:
if name == "bios" and not compile_bios:
pass
else:
dst_dir = os.path.join(self.software_dir, name)
makefile = os.path.join(src_dir, "Makefile")
if self.compile_software:
subprocess.check_call(["make", "-C", dst_dir, "-f", makefile])
def _initialize_rom_software(self):
bios_file = os.path.join(self.software_dir, "bios", "bios.bin")
bios_data = soc_core.get_mem_data(bios_file, self.soc.cpu.endianness)
self.soc.initialize_rom(bios_data)
def build(self, **kwargs):
self.soc.platform.output_dir = self.output_dir
os.makedirs(self.gateware_dir, exist_ok=True)
os.makedirs(self.software_dir, exist_ok=True)
self.soc.finalize()
#assert(False)
self._generate_includes()
self._generate_csr_map()
self._generate_mem_region_map()
if self.soc.cpu_type is not None:
if self.soc.cpu.use_rom:
self._prepare_rom_software()
self._generate_rom_software(not self.soc.integrated_rom_initialized)
if self.soc.integrated_rom_size and self.compile_software:
if not self.soc.integrated_rom_initialized:
self._initialize_rom_software()
if "run" not in kwargs:
kwargs["run"] = self.compile_gateware
vns = self.soc.build(build_dir=self.gateware_dir, **kwargs)
self.soc.do_exit(vns=vns)
return vns
def builder_args(parser):
parser.add_argument("--output-dir", default=None,
help="base output directory for generated "
"source files and binaries (customizable "
"with --{gateware,software,include,generated}-dir)")
parser.add_argument("--gateware-dir", default=None,
help="output directory for gateware files")
parser.add_argument("--software-dir", default=None,
help="base output directory for software files")
parser.add_argument("--include-dir", default=None,
help="output directory for header files")
parser.add_argument("--generated-dir", default=None,
help="output directory for various generated files")
parser.add_argument("--no-compile-software", action="store_true",
help="do not compile the software, only generate "
"build infrastructure")
parser.add_argument("--no-compile-gateware", action="store_true",
help="do not compile the gateware, only generate "
"HDL source files and build scripts")
parser.add_argument("--csr-csv", default=None,
help="store CSR map in CSV format into the "
"specified file")
parser.add_argument("--csr-json", default=None,
help="store CSR map in JSON format into the "
"specified file")
parser.add_argument("--csr-svd", default=None,
help="store CSR map in SVD format into the "
"specified file")
parser.add_argument("--memory-x", default=None,
help="store Mem regions in memory-x format into the "
"specified file")
def builder_argdict(args):
return {
"output_dir": args.output_dir,
"gateware_dir": args.gateware_dir,
"software_dir": args.software_dir,
"include_dir": args.include_dir,
"generated_dir": args.generated_dir,
"compile_software": not args.no_compile_software,
"compile_gateware": not args.no_compile_gateware,
"csr_csv": args.csr_csv,
"csr_json": args.csr_json,
"csr_svd": args.csr_svd,
"memory_x": args.memory_x,
}

@ -0,0 +1,265 @@
#
# This file is part of LiteX.
#
# This file is Copyright (c) 2015 Sebastien Bourdeauducq <sb@m-labs.hk>
# This file is Copyright (c) 2015-2019 Florent Kermarrec <florent@enjoy-digital.fr>
# This file is Copyright (c) 2018-2019 Antmicro <www.antmicro.com>
# This file is Copyright (c) 2018 Sergiusz Bazanski <q3k@q3k.org>
# This file is Copyright (c) 2016-2017 Tim 'mithro' Ansell <mithro@mithis.com>
# This file is Copyright (c) 2018 William D. Jones <thor0505@comcast.net>
# This file is Copyright (c) 2020 Xiretza <xiretza@xiretza.xyz>
# This file is Copyright (c) 2020 Piotr Esden-Tempski <piotr@esden.net>
# SPDX-License-Identifier: BSD-2-Clause
import os
import subprocess
import struct
import shutil
from litex import get_data_mod
from litex.build.tools import write_to_file
from litex.soc.integration import export, soc_core
from litex.soc.cores import cpu
__all__ = [
"soc_software_packages",
"soc_directory",
"Builder",
"builder_args",
"builder_argdict"
]
soc_software_packages = [
"libcompiler_rt",
"libbase",
"liblitedram",
"libliteeth",
"liblitespi",
"liblitesdcard",
"bios"
]
soc_directory = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
def _makefile_escape(s):
return s.replace("\\", "\\\\")
class Builder:
def __init__(self, soc,
output_dir = None,
gateware_dir = None,
software_dir = None,
include_dir = None,
generated_dir = None,
compile_software = True,
compile_gateware = True,
csr_json = None,
csr_csv = None,
csr_svd = None,
memory_x = None,
bios_options = []):
self.soc = soc
# From Python doc: makedirs() will become confused if the path elements to create include '..'
self.output_dir = os.path.abspath(output_dir or os.path.join("build", soc.platform.name))
self.gateware_dir = os.path.abspath(gateware_dir or os.path.join(self.output_dir, "gateware"))
self.software_dir = os.path.abspath(software_dir or os.path.join(self.output_dir, "software"))
self.include_dir = os.path.abspath(include_dir or os.path.join(self.software_dir, "include"))
self.generated_dir = os.path.abspath(generated_dir or os.path.join(self.include_dir, "generated"))
self.compile_software = compile_software
self.compile_gateware = compile_gateware
self.csr_csv = csr_csv
self.csr_json = csr_json
self.csr_svd = csr_svd
self.memory_x = memory_x
self.bios_options = bios_options
self.software_packages = []
for name in soc_software_packages:
self.add_software_package(name)
def add_software_package(self, name, src_dir=None):
if src_dir is None:
src_dir = os.path.join(soc_directory, "software", name)
self.software_packages.append((name, src_dir))
def _generate_includes(self):
os.makedirs(self.include_dir, exist_ok=True)
os.makedirs(self.generated_dir, exist_ok=True)
if self.soc.cpu_type not in [None, "zynq7000"]:
variables_contents = []
def define(k, v):
variables_contents.append("{}={}\n".format(k, _makefile_escape(v)))
for k, v in export.get_cpu_mak(self.soc.cpu, self.compile_software):
define(k, v)
define(
"COMPILER_RT_DIRECTORY",
get_data_mod("software", "compiler_rt").data_location)
define("SOC_DIRECTORY", soc_directory)
variables_contents.append("export BUILDINC_DIRECTORY\n")
define("BUILDINC_DIRECTORY", self.include_dir)
for name, src_dir in self.software_packages:
define(name.upper() + "_DIRECTORY", src_dir)
for bios_option in self.bios_options:
assert bios_option in ["TERM_NO_HIST", "TERM_MINI", "TERM_NO_COMPLETE"]
define(bios_option, "1")
write_to_file(
os.path.join(self.generated_dir, "variables.mak"),
"".join(variables_contents))
write_to_file(
os.path.join(self.generated_dir, "output_format.ld"),
export.get_linker_output_format(self.soc.cpu))
write_to_file(
os.path.join(self.generated_dir, "regions.ld"),
export.get_linker_regions(self.soc.mem_regions))
write_to_file(
os.path.join(self.generated_dir, "mem.h"),
export.get_mem_header(self.soc.mem_regions))
write_to_file(
os.path.join(self.generated_dir, "soc.h"),
export.get_soc_header(self.soc.constants))
write_to_file(
os.path.join(self.generated_dir, "csr.h"),
export.get_csr_header(
regions = self.soc.csr_regions,
constants = self.soc.constants,
csr_base = self.soc.mem_regions['csr'].origin
)
)
write_to_file(
os.path.join(self.generated_dir, "git.h"),
export.get_git_header()
)
if hasattr(self.soc, "sdram"):
from litedram.init import get_sdram_phy_c_header
write_to_file(os.path.join(self.generated_dir, "sdram_phy.h"),
get_sdram_phy_c_header(
self.soc.sdram.controller.settings.phy,
self.soc.sdram.controller.settings.timing))
def _generate_csr_map(self):
if self.csr_json is not None:
csr_dir = os.path.dirname(os.path.realpath(self.csr_json))
os.makedirs(csr_dir, exist_ok=True)
write_to_file(self.csr_json, export.get_csr_json(self.soc.csr_regions, self.soc.constants, self.soc.mem_regions))
if self.csr_csv is not None:
csr_dir = os.path.dirname(os.path.realpath(self.csr_csv))
os.makedirs(csr_dir, exist_ok=True)
write_to_file(self.csr_csv, export.get_csr_csv(self.soc.csr_regions, self.soc.constants, self.soc.mem_regions))
if self.csr_svd is not None:
svd_dir = os.path.dirname(os.path.realpath(self.csr_svd))
os.makedirs(svd_dir, exist_ok=True)
write_to_file(self.csr_svd, export.get_csr_svd(self.soc))
def _generate_mem_region_map(self):
if self.memory_x is not None:
memory_x_dir = os.path.dirname(os.path.realpath(self.memory_x))
os.makedirs(memory_x_dir, exist_ok=True)
write_to_file(self.memory_x, export.get_memory_x(self.soc))
def _prepare_rom_software(self):
for name, src_dir in self.software_packages:
dst_dir = os.path.join(self.software_dir, name)
os.makedirs(dst_dir, exist_ok=True)
def _generate_rom_software(self, compile_bios=True):
for name, src_dir in self.software_packages:
if name == "bios" and not compile_bios:
pass
else:
dst_dir = os.path.join(self.software_dir, name)
makefile = os.path.join(src_dir, "Makefile")
if self.compile_software:
subprocess.check_call(["make", "-C", dst_dir, "-f", makefile])
def _initialize_rom_software(self):
bios_file = os.path.join(self.software_dir, "bios", "bios.bin")
bios_data = soc_core.get_mem_data(bios_file, self.soc.cpu.endianness)
self.soc.initialize_rom(bios_data)
def build(self, **kwargs):
self.soc.platform.output_dir = self.output_dir
os.makedirs(self.gateware_dir, exist_ok=True)
os.makedirs(self.software_dir, exist_ok=True)
self.soc.finalize()
self._generate_includes()
self._generate_csr_map()
self._generate_mem_region_map()
if self.soc.cpu_type is not None:
if self.soc.cpu.use_rom:
self._prepare_rom_software()
self._generate_rom_software(not self.soc.integrated_rom_initialized)
if self.soc.integrated_rom_size and self.compile_software:
if not self.soc.integrated_rom_initialized:
self._initialize_rom_software()
if "run" not in kwargs:
kwargs["run"] = self.compile_gateware
vns = self.soc.build(build_dir=self.gateware_dir, **kwargs)
self.soc.do_exit(vns=vns)
return vns
def builder_args(parser):
parser.add_argument("--output-dir", default=None,
help="base output directory for generated "
"source files and binaries (customizable "
"with --{gateware,software,include,generated}-dir)")
parser.add_argument("--gateware-dir", default=None,
help="output directory for gateware files")
parser.add_argument("--software-dir", default=None,
help="base output directory for software files")
parser.add_argument("--include-dir", default=None,
help="output directory for header files")
parser.add_argument("--generated-dir", default=None,
help="output directory for various generated files")
parser.add_argument("--no-compile-software", action="store_true",
help="do not compile the software, only generate "
"build infrastructure")
parser.add_argument("--no-compile-gateware", action="store_true",
help="do not compile the gateware, only generate "
"HDL source files and build scripts")
parser.add_argument("--csr-csv", default=None,
help="store CSR map in CSV format into the "
"specified file")
parser.add_argument("--csr-json", default=None,
help="store CSR map in JSON format into the "
"specified file")
parser.add_argument("--csr-svd", default=None,
help="store CSR map in SVD format into the "
"specified file")
parser.add_argument("--memory-x", default=None,
help="store Mem regions in memory-x format into the "
"specified file")
def builder_argdict(args):
return {
"output_dir": args.output_dir,
"gateware_dir": args.gateware_dir,
"software_dir": args.software_dir,
"include_dir": args.include_dir,
"generated_dir": args.generated_dir,
"compile_software": not args.no_compile_software,
"compile_gateware": not args.no_compile_gateware,
"csr_csv": args.csr_csv,
"csr_json": args.csr_json,
"csr_svd": args.csr_svd,
"memory_x": args.memory_x,
}

@ -56,7 +56,7 @@ def SoCConstant(value):
class SoCRegion:
# 14.02.21/KQ Cache disabled (use own) def __init__(self, origin=None, size=None, mode="rw", cached=True, linker=False):
def __init__(self, origin=None, size=None, mode="rw", cached=False, linker=False):
def __init__(self, origin=None, size=None, mode="rw", cached=False, linker=False): # Unloadable w/ un-cached?!!
self.logger = logging.getLogger("SoCRegion")
self.origin = origin
self.size = size
@ -193,7 +193,7 @@ class SoCBusHandler(Module):
self.regions[name] = region
# Else add region and check for overlaps.
else:
if not region.cached:
if False: # 17.02.21/KQ Removed: if not region.cached:
if not self.check_region_is_io(region):
self.logger.error("{} Region {}: {}.".format(
colorer(name),
@ -822,6 +822,7 @@ class SoC(Module):
bus = getattr(self.csr_bridge, self.bus.standard.replace('-', '_'))
self.bus.add_slave("csr", bus, csr_region)
self.csr.add_master(name="bridge", master=self.csr_bridge.csr)
#self.csr.add_master(name="cpu2csr", master=self.csr_bridge.csr) # 17.02.21/KQ FIXME: Test?!
self.add_config("CSR_DATA_WIDTH", self.csr.data_width)
self.add_config("CSR_ALIGNMENT", self.csr.alignment)
@ -849,14 +850,17 @@ class SoC(Module):
# Update SoC with CPU constraints
for n, (origin, size) in enumerate(self.cpu.io_regions.items()):
self.bus.add_region("io{}".format(n), SoCIORegion(origin=origin, size=size, cached=False))
# 14.02.21/KQ removed self.mem_map.update(self.cpu.mem_map) # FIXME
# 14.02.21/KQ removed self.mem_map.update(self.cpu.mem_map) # FIXME: Nec. for cpu=None
self.mem_map.update(self.cpu.mem_map) # TODO: connect missing?
# Add Bus Masters/CSR/IRQs
if not isinstance(self.cpu, (cpu.CPUNone, cpu.Zynq7000)):
if reset_address is None:
reset_address = self.mem_map["rom"]
self.cpu.set_reset_address(reset_address)
for n, cpu_bus in enumerate(self.cpu.periph_buses):
self.bus.add_master(name="cpu_bus{}".format(n), master=cpu_bus)
# TODO: 18.02.21/KQ No peripheral bus for now
#for n, cpu_bus in enumerate(self.cpu.periph_buses):
# self.bus.add_master(name="cpu_bus{}".format(n), master=cpu_bus)
#assert(False)
self.csr.add("cpu", use_loc_if_exists=True)
if hasattr(self.cpu, "interrupt"):
for name, loc in self.cpu.interrupts.items():
@ -1198,96 +1202,98 @@ class LiteXSoC(SoC):
)
# Connect CPU's direct memory buses to LiteDRAM --------------------------------------------
if len(self.cpu.memory_buses):
# When CPU has at least a direct memory bus, connect them directly to LiteDRAM.
for mem_bus in self.cpu.memory_buses:
if hasattr(self.cpu, "memory_buses"): # 17.02.21/KQ Verify attribute existence ...
if len(self.cpu.memory_buses):
# When CPU has at least a direct memory bus, connect them directly to LiteDRAM.
for mem_bus in self.cpu.memory_buses:
# Request a LiteDRAM native port.
port = self.sdram.crossbar.get_port()
port.data_width = 2**int(log2(port.data_width)) # Round to nearest power of 2.
# Check if bus is an AXI bus and connect it.
if isinstance(mem_bus, axi.AXIInterface):
# If same data_width, connect it directly.
if port.data_width == mem_bus.data_width:
self.logger.info("Matching AXI MEM data width ({})\n".format(port.data_width))
self.submodules += LiteDRAMAXI2Native(
axi = self.cpu.mem_axi,
port = port,
base_address = self.bus.regions["main_ram"].origin)
# If different data_width, do the adaptation and connect it via Wishbone.
else:
self.logger.info("Converting MEM data width: {} to {} via Wishbone".format(
port.data_width,
self.cpu.mem_axi.data_width))
# FIXME: replace WB data-width converter with native AXI converter!!!
mem_wb = wishbone.Interface(
data_width = self.cpu.mem_axi.data_width,
adr_width = 32-log2_int(self.cpu.mem_axi.data_width//8))
# NOTE: AXI2Wishbone FSMs must be reset with the CPU!
mem_a2w = ResetInserter()(axi.AXI2Wishbone(
axi = self.cpu.mem_axi,
wishbone = mem_wb,
base_address = 0))
self.comb += mem_a2w.reset.eq(ResetSignal() | self.cpu.reset)
self.submodules += mem_a2w
litedram_wb = wishbone.Interface(port.data_width)
self.submodules += LiteDRAMWishbone2Native(
wishbone = litedram_wb,
port = port,
base_address = origin)
self.submodules += wishbone.Converter(mem_wb, litedram_wb)
# Check if bus is a Native bus and connect it.
if isinstance(mem_bus, LiteDRAMNativePort):
# If same data_width, connect it directly.
if port.data_width == mem_bus.data_width:
self.comb += mem_bus.cmd.connect(port.cmd)
self.comb += mem_bus.wdata.connect(port.wdata)
self.comb += port.rdata.connect(mem_bus.rdata)
# Else raise Error.
else:
raise NotImplementedError
# Connect Main bus to LiteDRAM (with optional L2 Cache) ------------------------------------
if hasattr(self.cpu, "memory_buses"): # 17.02.21/KQ Verify attribute existence ...
connect_main_bus_to_dram = (
# No memory buses.
(not len(self.cpu.memory_buses)) or
# Memory buses but no DMA bus.
(len(self.cpu.memory_buses) and not hasattr(self.cpu, "dma_bus"))
)
if connect_main_bus_to_dram:
# Request a LiteDRAM native port.
port = self.sdram.crossbar.get_port()
port.data_width = 2**int(log2(port.data_width)) # Round to nearest power of 2.
# Check if bus is an AXI bus and connect it.
if isinstance(mem_bus, axi.AXIInterface):
# If same data_width, connect it directly.
if port.data_width == mem_bus.data_width:
self.logger.info("Matching AXI MEM data width ({})\n".format(port.data_width))
self.submodules += LiteDRAMAXI2Native(
axi = self.cpu.mem_axi,
port = port,
base_address = self.bus.regions["main_ram"].origin)
# If different data_width, do the adaptation and connect it via Wishbone.
else:
self.logger.info("Converting MEM data width: {} to {} via Wishbone".format(
port.data_width,
self.cpu.mem_axi.data_width))
# FIXME: replace WB data-width converter with native AXI converter!!!
mem_wb = wishbone.Interface(
data_width = self.cpu.mem_axi.data_width,
adr_width = 32-log2_int(self.cpu.mem_axi.data_width//8))
# NOTE: AXI2Wishbone FSMs must be reset with the CPU!
mem_a2w = ResetInserter()(axi.AXI2Wishbone(
axi = self.cpu.mem_axi,
wishbone = mem_wb,
base_address = 0))
self.comb += mem_a2w.reset.eq(ResetSignal() | self.cpu.reset)
self.submodules += mem_a2w
litedram_wb = wishbone.Interface(port.data_width)
self.submodules += LiteDRAMWishbone2Native(
wishbone = litedram_wb,
port = port,
base_address = origin)
self.submodules += wishbone.Converter(mem_wb, litedram_wb)
# Check if bus is a Native bus and connect it.
if isinstance(mem_bus, LiteDRAMNativePort):
# If same data_width, connect it directly.
if port.data_width == mem_bus.data_width:
self.comb += mem_bus.cmd.connect(port.cmd)
self.comb += mem_bus.wdata.connect(port.wdata)
self.comb += port.rdata.connect(mem_bus.rdata)
# Else raise Error.
else:
raise NotImplementedError
# Connect Main bus to LiteDRAM (with optional L2 Cache) ------------------------------------
connect_main_bus_to_dram = (
# No memory buses.
(not len(self.cpu.memory_buses)) or
# Memory buses but no DMA bus.
(len(self.cpu.memory_buses) and not hasattr(self.cpu, "dma_bus"))
)
if connect_main_bus_to_dram:
# Request a LiteDRAM native port.
port = self.sdram.crossbar.get_port()
port.data_width = 2**int(log2(port.data_width)) # Round to nearest power of 2.
# Create Wishbone Slave.
wb_sdram = wishbone.Interface()
self.bus.add_slave("main_ram", wb_sdram)
# L2 Cache
if l2_cache_size != 0:
# Insert L2 cache inbetween Wishbone bus and LiteDRAM
l2_cache_size = max(l2_cache_size, int(2*port.data_width/8)) # Use minimal size if lower
l2_cache_size = 2**int(log2(l2_cache_size)) # Round to nearest power of 2
l2_cache_data_width = max(port.data_width, l2_cache_min_data_width)
l2_cache = wishbone.Cache(
cachesize = l2_cache_size//4,
master = wb_sdram,
slave = wishbone.Interface(l2_cache_data_width),
reverse = l2_cache_reverse)
if l2_cache_full_memory_we:
l2_cache = FullMemoryWE()(l2_cache)
self.submodules.l2_cache = l2_cache
litedram_wb = self.l2_cache.slave
else:
litedram_wb = wishbone.Interface(port.data_width)
self.submodules += wishbone.Converter(wb_sdram, litedram_wb)
self.add_config("L2_SIZE", l2_cache_size)
# Wishbone Slave <--> LiteDRAM bridge
self.submodules.wishbone_bridge = LiteDRAMWishbone2Native(
wishbone = litedram_wb,
port = port,
base_address = self.bus.regions["main_ram"].origin)
# Create Wishbone Slave.
wb_sdram = wishbone.Interface()
self.bus.add_slave("main_ram", wb_sdram)
# L2 Cache
if l2_cache_size != 0:
# Insert L2 cache inbetween Wishbone bus and LiteDRAM
l2_cache_size = max(l2_cache_size, int(2*port.data_width/8)) # Use minimal size if lower
l2_cache_size = 2**int(log2(l2_cache_size)) # Round to nearest power of 2
l2_cache_data_width = max(port.data_width, l2_cache_min_data_width)
l2_cache = wishbone.Cache(
cachesize = l2_cache_size//4,
master = wb_sdram,
slave = wishbone.Interface(l2_cache_data_width),
reverse = l2_cache_reverse)
if l2_cache_full_memory_we:
l2_cache = FullMemoryWE()(l2_cache)
self.submodules.l2_cache = l2_cache
litedram_wb = self.l2_cache.slave
else:
litedram_wb = wishbone.Interface(port.data_width)
self.submodules += wishbone.Converter(wb_sdram, litedram_wb)
self.add_config("L2_SIZE", l2_cache_size)
# Wishbone Slave <--> LiteDRAM bridge
self.submodules.wishbone_bridge = LiteDRAMWishbone2Native(
wishbone = litedram_wb,
port = port,
base_address = self.bus.regions["main_ram"].origin)
# Add Ethernet ---------------------------------------------------------------------------------
def add_ethernet(self, name="ethmac", phy=None):

@ -65,7 +65,7 @@ class SoCCore(LiteXSoC):
bus_address_width = 32,
bus_timeout = 1e6,
# CPU parameters
cpu_type = "None", #"vexriscv",
cpu_type = "risq5", #"None", #"vexriscv",
cpu_reset_address = None,
cpu_variant = None,
cpu_cls = None,

@ -134,7 +134,7 @@ class BaseSoC(SoCCore):
ident = "LiteX SoC on Colorlight " + board.upper(),
ident_version = True,
**kwargs)
# CRG --------------------------------------------------------------------------------------
with_rst = kwargs["uart_name"] not in ["serial", "bridge"] # serial_rx shared with user_btn_n.
with_usb_pll = kwargs.get("uart_name", None) == "usb_acm"
@ -158,8 +158,7 @@ class BaseSoC(SoCCore):
l2_cache_size = kwargs.get("l2_size", 8192),
l2_cache_min_data_width = kwargs.get("min_l2_data_width", 128),
l2_cache_reverse = True
)
#self.user_port = self.sdram.crossbar.get_port() # TODO: Implement access & test!!!
)
# Ethernet / Etherbone ---------------------------------------------------------------------
if with_ethernet or with_etherbone:
@ -175,7 +174,17 @@ class BaseSoC(SoCCore):
ip_address = ip_address,
mac_address = mac_address,
)
# FIXME: Added 2nd master to csr (after master0)
##from litex.soc.interconnect import wishbone
##self.csr.add_master(name="cpu2csr", master=wishbone.Interface(8,14))
#from litex.soc.interconnect import wishbone
#self.cpu2csr = cpu2csr = wishbone.Interface()
# Signals: ack, adr(14), bte(2), cti(3), cyc, dat_r(8), dat_w(8), err, sel, stb, we
# _do_transaction, data_width8, adr_width=14
# But for (etherbone) 'bridge' only these are used:
# Signals: adr(14), dat_r(8), dat_w(8), we
# data_width8, adr_width=14
#self.add_wb_master(self.etherbone.bus) # add_csr_bridge(self.mem_map["csr"], False) # fails
# Base counter (used for clocking)
#counter = Signal(32, reset_less=True) # 32-Bit counter
@ -190,6 +199,8 @@ class BaseSoC(SoCCore):
self.submodules.systime = systime = SysTime(comparecount=0x0000EA90)
self.add_csr("systime")
# Use ctrl.scratch.storage 32-bit (=0x12345678) for testing!
# DRAM test
MAXWORDS = 32 # Transfer length 32 x 32-bit, FIFO depth (511 L1 cache currently possible = 9-bit!)
MAXMEMWORDS = 4 # Transfer length 4 x 32-bit = 16 byte (LU cache)
@ -235,11 +246,11 @@ class BaseSoC(SoCCore):
# CLINT mtime/mtimecmp memory mapped 64-bit timers (acc. to RISC-V spec.)
self.submodules.clint = clint = Clint(comparecount=0x0000EA90)
self.add_csr("clint")
# Integrate my RISC-V cpu clone
RAMWAITTIME=128 # 32-bit max. for testing ... (TODO: 8-bit 128 seems to work as well)
LUWAITTIME=24
self.submodules.risq5 = risq5 = Risq5Core(
self.submodules.risq5ext = risq5ext = Risq5Core(
RAMWaitTime=RAMWAITTIME,
LU_CacheWait=LUWAITTIME,
L1CacheSize=MAXWORDS,
@ -249,12 +260,12 @@ class BaseSoC(SoCCore):
SU_Unit=fpga2dram,
clint = clint
)
self.add_csr("risq5")
self.add_csr("risq5ext")
# USERLED (on-board LED) used for debugging
if kwargs["uart_name"] not in ["serial", "bridge"]: # only w/ uart-name=crossover option:
self.comb += platform.request("user_led_n").eq(~(risq5.b32mode.storage[31]))
self.comb += platform.request("user_led_n").eq(~(risq5ext.b32mode.storage[31]))
# Build --------------------------------------------------------------------------------------------
def main():
@ -289,7 +300,7 @@ def main():
sys_clk_freq = args.sys_clk_freq,
use_internal_osc = args.use_internal_osc,
sdram_rate = args.sdram_rate,
**soc_core_argdict(args))
**soc_core_argdict(args))
# 32MBit SPIFlash ------------------------------------------------------------------------
flashbase = 0xc0000000

@ -13,6 +13,12 @@ uint32_t gettimer(void)
return st; // returend in a0
}
extern uint32_t getscratch(void);
uint32_t getscratch(void)
{
return ctrl_scratch_read(); // a0 -- not inlined now ...
}
#pragma GCC diagnostic ignored "-Wunused-function"
static void start(void)
{
@ -41,7 +47,7 @@ static void start(void)
loop: addi t0,t0,1 # Stupid job loop \n\
addi t0,t0,2 # ... \n\
add t2,zero,zero # Reset t2 \n\
call gettimer # Read systime clock (rc=a0) \n\
call getscratch # Read systime clock (rc=a0) \n\
mv t5,a0 # Store reading \n\
j loop # Loop jump \n\
nop # \n\

Loading…
Cancel
Save