Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Vamsi Vytla 2021-02-15 09:29:47 -08:00
commit 385dec8560
62 changed files with 1294 additions and 350 deletions

View File

@ -1,6 +1,7 @@
graft litex/build/sim
graft litex/soc/software
graft litex/soc/cores/cpu/blackparrot
graft litex/soc/cores/cpu/cv32e40p
graft litex/soc/cores/cpu/lm32
graft litex/soc/cores/cpu/microwatt
graft litex/soc/cores/cpu/minerva
@ -9,3 +10,5 @@ graft litex/soc/cores/cpu/picorv32
graft litex/soc/cores/cpu/rocket
graft litex/soc/cores/cpu/serv
graft litex/soc/cores/cpu/vexriscv
graft litex/soc/cores/cpu/vexriscv_smp
graft litex/soc/cores/cpu/zynq7000

View File

@ -14,6 +14,8 @@ The common components of a SoC are provided directly: Buses and Streams (Wishbon
Think of Migen as a toolbox to create FPGA designs in Python and LiteX as a
SoC builder to create/develop/debug FPGA SoCs in Python.
**Want to get started and/or looking for documentation? Make sure to visit the [Wiki](https://github.com/enjoy-digital/litex/wiki)!**
**A question or want to get in touch? Our IRC channel is [#litex at freenode.net](https://webchat.freenode.net/?channels=litex)**
# Typical LiteX design flow:

View File

@ -396,8 +396,7 @@ class GenericPlatform:
# resolve signal names in constraints
sc = self.constraint_manager.get_sig_constraints()
named_sc = [(vns.get_name(sig), pins, others, resource)
for sig, pins, others, resource in sc
if not re.match(r"^X+$", ''.join(pins))]
for sig, pins, others, resource in sc]
# resolve signal names in platform commands
pc = self.constraint_manager.get_platform_commands()
named_pc = []

View File

@ -26,7 +26,8 @@ def _build_cst(named_sc, named_pc):
flat_sc.append((name, pins[0], other))
for name, pin, other in flat_sc:
lines.append(f"IO_LOC \"{name}\" {pin};")
if pin != "X":
lines.append(f"IO_LOC \"{name}\" {pin};")
for c in other:
if isinstance(c, IOStandard):

View File

@ -15,8 +15,13 @@ class OpenFPGALoader(GenericProgrammer):
def __init__(self, board):
self.board = board
def load_bitstream(self, bitstream_file, flash=False):
def load_bitstream(self, bitstream_file):
cmd = ["openFPGALoader", "--board", self.board, "--bitstream", bitstream_file]
if flash:
cmd.append("--write-flash")
self.call(cmd)
def flash(self, address, data_file):
cmd = ["openFPGALoader", "--board", self.board, "--write-flash", "--bitstream", data_file]
if address:
cmd.append("--offset")
cmd.append(address)
self.call(cmd)

View File

@ -42,7 +42,7 @@ class OpenOCD(GenericProgrammer):
def stream(self, port=20000):
"""
Create a Telnet server to stream data to/from the internal JTAG TAP of the FPGA
Create a TCP server to stream data to/from the internal JTAG TAP of the FPGA
Wire format: 10 bits LSB first
Host to Target:
@ -64,6 +64,7 @@ proc jtagstream_poll {tap tx n} {
foreach txj [split $tx ""] {
lset txi $i 1 [format 0x%4.4X [expr 0x201 | ([scan $txj %c] << 1)]]
incr i
#echo tx[scan $txj %c]
}
set txi [concat {*}$txi]
set rxi [split [drscan $tap {*}$txi -endstate DRPAUSE] " "]
@ -95,12 +96,13 @@ proc jtagstream_drain {tap tx chunk_rx max_rx} {
proc jtagstream_rxtx {tap client is_poll} {
if {![$client eof]} {
if {!$is_poll} {
set tx [$client gets]
set tx [$client read 1]
} else {
set tx ""
}
set rx [jtagstream_drain $tap $tx 64 4096]
if {[string length $rx]} {
#echo [string length $rx]
$client puts -nonewline $rx
}
if {$is_poll} {

318
litex/build/sim/gtkwave.py Normal file
View File

@ -0,0 +1,318 @@
# This file is part of LiteX.
#
# SPDX-License-Identifier: BSD-2-Clause
#
import os
import re
from typing import Optional, Sequence, Any, Callable, Generator, Dict, Tuple
from migen import *
from migen.fhdl.namer import Namespace
class SigTrace:
"""Trace configuration for a single signal"""
def __init__(self,
name: str,
signal: Signal,
alias: str = None,
color: str = None,
filter_file: str = None):
self.name = name
self.signal = signal
self.alias = alias
self.color = color
self.filter_file = filter_file
# Type aliases
Regex = str
SigMapper = Callable[[Sequence[SigTrace]], Sequence[SigTrace]]
class GTKWSave:
"""Generator of pretty GTKWave savefiles from SoC signals
Usage example:
```
builder = Builder(soc, **builder_kwargs)
vns = builder.build(run=False, **build_kwargs)
with GTKWSave(vns, savefile=savefile, dumpfile=dumpfile) as gtkw:
gtkw.clocks()
gtkw.fsm_states(soc)
gtkw.add(soc.bus.slaves["main_ram"])
```
"""
def __init__(self,
vns: Namespace,
savefile: str,
dumpfile: str,
filtersdir: str = None,
prefix: str = "TOP.sim."):
"""Crate savefile generator for the namespace.
`prefix` is prepended to all signal names and defaults to the one used by Litex simulator.
"""
self.vns = vns # Namespace output of Builder.build, required to resolve signal names
self.prefix = prefix
self.savefile = savefile
self.dumpfile = dumpfile
self.filtersdir = filtersdir
if self.filtersdir is None:
self.filtersdir = os.path.dirname(self.savefile)
def __enter__(self):
# pyvcd: https://pyvcd.readthedocs.io/en/latest/vcd.gtkw.html
from vcd.gtkw import GTKWSave
self.file = open(self.savefile, "w")
self.gtkw = GTKWSave(self.file)
self.gtkw.dumpfile(self.dumpfile)
modules = self.prefix.rstrip(".").split(".")
for i in range(len(modules)):
self.gtkw.treeopen(".".join(modules[:i + 1]))
self.gtkw.sst_expanded(True)
return self
def __exit__(self, type, value, traceback):
self.file.close()
print("\nGenerated GTKWave save file at: {}\n".format(self.savefile))
def name(self, sig: Signal) -> str:
bits = ""
if len(sig) > 1:
bits = "[{}:0]".format(len(sig) - 1)
return self.vns.get_name(sig) + bits
def signal(self, signal: Signal):
self.gtkw.trace(self.prefix + self.name(signal))
def common_prefix(self, names: Sequence[str]) -> str:
prefix = os.path.commonprefix(names)
last_underscore = prefix.rfind("_")
return prefix[:last_underscore + 1]
def group(self,
signals: Sequence[Signal],
group_name: str = None,
alias: bool = True,
closed: bool = True,
mappers: Optional[Sequence[SigMapper]] = None,
translation_files: Optional[Sequence[str]] = None,
**kwargs):
mappers = mappers or []
translation_files = translation_files or {}
if len(signals) == 1:
return self.signal(signals[0])
names = [self.name(s) for s in signals]
common = self.common_prefix(names)
make_alias = (lambda n: n[len(common):]) if alias else (lambda n: n)
sigs = [
SigTrace(name=n, signal=s, alias=make_alias(n))
for i, (s, n) in enumerate(zip(signals, names))
]
for sig, file in zip(sigs, translation_files):
sig.filter_file = file
for mapper in mappers:
sigs = list(mapper(sigs))
with self.gtkw.group(group_name or common.strip("_"), closed=closed):
for s in sigs:
self.gtkw.trace(self.prefix + s.name, alias=s.alias, color=s.color,
translate_filter_file=s.filter_file, **kwargs)
def by_regex(self, regex: Regex, **kwargs):
pattern = re.compile(regex)
signals = list(filter(
lambda sig: pattern.search(self.vns.pnd[sig]),
self.vns.pnd.keys()))
assert len(signals) > 0, "No match found for {}".format(regex)
return self.group(signals, **kwargs)
def clocks(self, **kwargs):
clks = [cd.clk for cd in self.vns.clock_domains]
self.group(clks, group_name="clocks", alias=False, closed=False, **kwargs)
def add(self, obj: Any, **kwargs):
# TODO: add automatic default handlers for Litex types (e.g. WishBone, AXI, streams, ...)
if isinstance(obj, Record):
self.group([s for s, _ in obj.iter_flat()], **kwargs)
elif isinstance(obj, Signal):
self.signal(obj)
else:
raise NotImplementedError(type(obj), obj)
def make_fsm_state_translation(self, fsm: FSM) -> str:
# generate filter file
from vcd.gtkw import make_translation_filter
translations = list(fsm.decoding.items())
filename = "filter__{}.txt".format(self._strip_bits(self.name(fsm.state)))
filepath = os.path.join(self.filtersdir, filename)
with open(filepath, 'w') as f:
f.write(make_translation_filter(translations, size=len(fsm.state)))
return filepath
def iter_submodules(self, parent: Module) -> Generator[Module, None, None]:
for name, module in getattr(parent, "_submodules", []):
yield module
yield from self.iter_submodules(module)
def make_fsm_state_alias(self, state: Signal):
# Try to improve state name, as the defaults are usually hard to decipher.
# This will make sure to include the name of the module that has the FSM,
# but still there are some issues, e.g. we always add number to all names.
alias = ""
for name, num in reversed(state.backtrace):
if alias.startswith(name):
continue
if name == "subfragments":
break
alias = "{}{}_{}".format(name, num, alias)
return alias.strip("_")
def fsm_states(self, soc: Module, alias: bool = True, **kwargs):
fsms = list(filter(lambda module: isinstance(module, FSM), self.iter_submodules(soc)))
states = [fsm.state for fsm in fsms]
files = [self.make_fsm_state_translation(fsm) for fsm in fsms]
if alias:
aliases = {state: self.make_fsm_state_alias(state) for state in states}
def add_alias(sig):
sig.alias = aliases.get(sig.signal, None)
return sig
kwargs["mappers"] = [lambda sigs: map(add_alias, sigs)] + kwargs.get("mappers", [])
self.group(states, group_name="FSM states", translation_files=files, **kwargs)
@staticmethod
def _strip_bits(name: str) -> str:
if name.endswith("]") and "[" in name:
name = name[:name.rfind("[")]
return name
# Generic mappers ----------------------------------------------------------------------------------
def _regex_map(
sig: SigTrace,
patterns: Sequence[Regex],
on_match: Callable[[SigTrace, Regex], Optional[SigTrace]],
on_no_match: Callable[[SigTrace], Optional[SigTrace]],
remove_bits: bool = True) -> Optional[SigTrace]:
# Given `patterns` return `on_match(sig, pattern)` if any pattern matches or else `on_no_match(sig)`
alias = sig.alias
if remove_bits: # get rid of signal bits (e.g. wb_adr[29:0])
alias = GTKWSave._strip_bits(alias)
for pattern in patterns:
if pattern.search(alias):
return on_match(sig, pattern)
return on_no_match(sig)
def suffixes2re(strings: Sequence[str]) -> Sequence[Regex]:
return ["{}$".format(s) for s in strings]
def prefixes2re(strings: Sequence[str]) -> Sequence[Regex]:
return ["^{}".format(s) for s in strings]
def strings2re(strings: Sequence[str]) -> Sequence[Regex]:
return suffixes2re(prefixes2re(strings))
def regex_filter(patterns: Sequence[Regex], negate: bool = False, **kwargs) -> SigMapper:
"""Filter out the signals that do not match regex patterns (or do match if negate=True)."""
patterns = list(map(re.compile, patterns))
def filt(sigs):
def map_sig(sig):
return _regex_map(sig, patterns,
on_match = lambda s, p: (s if not negate else None),
on_no_match = lambda s: (None if not negate else s),
**kwargs)
return list(filter(None, map(map_sig, sigs)))
return filt
def regex_sorter(patterns: Sequence[Regex], unmatched_last: bool = True, **kwargs) -> SigMapper:
"""Sort signals accorting to the order of patterns. Unmatched are placed last/first."""
def sort(sigs):
order = {re.compile(pattern): i for i, pattern in enumerate(patterns)}
return sorted(sigs, key=lambda sig: _regex_map(sig, order.keys(),
on_match = lambda s, p: order[p],
on_no_match = lambda s: len(order) if unmatched_last else -1,
**kwargs))
return sort
def regex_colorer(
color_patterns: Dict[str, Sequence[Regex]],
default: Optional[str] = None,
**kwargs) -> SigMapper:
"""Apply colors to signals based on per-color patterns with an optional default on no match."""
colors = {}
for color, patterns in color_patterns.items():
for pattern in patterns:
colors[re.compile(pattern)] = color
def add_color(sig, color):
sig.color = color
def add_colors(sigs):
for sig in sigs:
_regex_map(sig, colors.keys(),
on_match = lambda s, p: add_color(s, colors[p]),
on_no_match = lambda s: add_color(s, default),
**kwargs)
return sigs
return add_colors
# Mappers ------------------------------------------------------------------------------------------
def wishbone_sorter(**kwargs) -> SigMapper:
suffixes = ["cyc", "stb", "ack", "adr", "we", "sel", "dat_w", "dat_r"]
return regex_sorter(suffixes2re(suffixes), **kwargs)
def wishbone_colorer(**kwargs) -> SigMapper:
return regex_colorer({
"normal": suffixes2re(["cyc", "stb", "ack"]),
"yellow": suffixes2re(["adr", "we", "sel"]),
"orange": suffixes2re(["dat_w"]),
"red": suffixes2re(["dat_r"]),
}, default="indigo", **kwargs)
def dfi_sorter(phases: bool = True, nphases_max: int = 8, **kwargs) -> SigMapper:
suffixes = [
"cas_n", "ras_n", "we_n",
"address", "bank",
"wrdata_en", "wrdata", "wrdata_mask",
"rddata_en", "rddata", "rddata_valid",
]
if phases:
patterns = []
for phase in range(nphases_max):
patterns.extend(["p{}_{}".format(phase, suffix) for suffix in suffixes])
else:
patterns = suffixes
return regex_sorter(suffixes2re(patterns), **kwargs)
def dfi_per_phase_colorer(nphases_max: int = 8, **kwargs) -> SigMapper:
colors = ["normal", "yellow", "orange", "red"]
color_patterns = {}
for p in range(nphases_max):
color = colors[p % len(colors)]
patterns = color_patterns.get(color, [])
patterns.append("p{}_".format(p))
color_patterns[color] = patterns
return regex_colorer(color_patterns, default="indigo", **kwargs)
def dfi_in_phase_colorer(**kwargs) -> SigMapper:
return regex_colorer({
"normal": suffixes2re(["cas_n", "ras_n", "we_n"]),
"yellow": suffixes2re(["address", "bank"]),
"orange": suffixes2re(["wrdata_en", "wrdata", "wrdata_mask"]),
"red": suffixes2re(["rddata_en", "rddata", "rddata_valid"]),
}, default="indigo", **kwargs)

View File

@ -23,7 +23,7 @@ def language_by_filename(name):
return "verilog"
elif extension in ["vhd", "vhdl", "vho"]:
return "vhdl"
elif extension in ["sv"]:
elif extension in ["sv", "svo"]:
return "systemverilog"
return None

View File

@ -110,13 +110,16 @@ class SymbiflowToolchain:
# FIXME: fine for now since only a few devices are supported, do more clever device re-mapping.
"xc7a35ticsg324-1L" : "xc7a50t_test",
"xc7a100tcsg324-1" : "xc7a100t_test",
"xc7a200t-sbg484-1" : "xc7a200t_test",
}[platform.device]
except KeyError:
raise ValueError(f"symbiflow_device is not specified")
if not self.bitstream_device:
try:
# bitstream_device points to a directory in prjxray database
# available bitstream_devices: artix7, kintex7, zynq7
self.bitstream_device = {
"xc7a": "artix7"
"xc7a": "artix7", # xc7a35t, xc7a50t, xc7a100t, xc7a200t
}[platform.device[:4]]
except KeyError:
raise ValueError(f"Unsupported device: {platform.device}")
@ -124,6 +127,7 @@ class SymbiflowToolchain:
self._partname = {
"xc7a35ticsg324-1L" : "xc7a35tcsg324-1",
"xc7a100tcsg324-1" : "xc7a100tcsg324-1",
"xc7a200t-sbg484-1" : "xc7a200tsbg484-1",
}.get(platform.device, platform.device)
def _generate_makefile(self, platform, build_name):

View File

@ -5,6 +5,7 @@
# SPDX-License-Identifier: BSD-2-Clause
from migen import *
from migen.genlib.resetsync import AsyncResetSynchronizer
from litex.soc.cores.clock.common import *

View File

@ -93,7 +93,6 @@ class USMMCM(XilinxClocking):
class USIDELAYCTRL(Module):
def __init__(self, cd_ref, cd_sys, reset_cycles=64, ready_cycles=64):
cd_sys.rst.reset = 1
self.clock_domains.cd_ic = ClockDomain()
ic_reset_counter = Signal(max=reset_cycles, reset=reset_cycles-1)
ic_reset = Signal(reset=1)
@ -109,6 +108,7 @@ class USIDELAYCTRL(Module):
ic_ready = Signal()
self.comb += self.cd_ic.clk.eq(cd_sys.clk)
self.sync.ic += [
cd_sys.rst.eq(1),
If(ic_ready,
If(ic_ready_counter != 0,
ic_ready_counter.eq(ic_ready_counter - 1)

View File

@ -77,6 +77,7 @@ from litex.soc.cores.cpu.picorv32 import PicoRV32
from litex.soc.cores.cpu.minerva import Minerva
from litex.soc.cores.cpu.vexriscv import VexRiscv
from litex.soc.cores.cpu.vexriscv_smp import VexRiscvSMP
from litex.soc.cores.cpu.ibex import Ibex
from litex.soc.cores.cpu.cv32e40p import CV32E40P
# RISC-V (64-bit)
@ -109,6 +110,7 @@ CPUS = {
"minerva" : Minerva,
"vexriscv" : VexRiscv,
"vexriscv_smp": VexRiscvSMP,
"ibex" : Ibex,
"cv32e40p" : CV32E40P,
# RISC-V (64-bit)

View File

@ -0,0 +1 @@
from litex.soc.cores.cpu.ibex.core import Ibex

View File

@ -0,0 +1,4 @@
.section .text, "ax", @progbits
.global boot_helper
boot_helper:
jr x13

View File

@ -0,0 +1,219 @@
#
# This file is part of LiteX.
#
# Copyright (c) 2021 Florent Kermarrec <florent@enjoy-digital.fr>
# Copyright (c) 2020 Antmicro <www.antmicro.com>
# SPDX-License-Identifier: BSD-2-Clause
import os
from migen import *
from litex.soc.interconnect import wishbone
from litex.soc.cores.cpu import CPU, CPU_GCC_TRIPLE_RISCV32
CPU_VARIANTS = ["standard"]
GCC_FLAGS = {
# /-------- Base ISA
# |/------- Hardware Multiply + Divide
# ||/----- Atomics
# |||/---- Compressed ISA
# ||||/--- Single-Precision Floating-Point
# |||||/-- Double-Precision Floating-Point
# imacfd
"standard": "-march=rv32imc -mabi=ilp32 ",
}
obi_layout = [
("req", 1),
("gnt", 1),
("addr", 32),
("we", 1),
("be", 4),
("wdata", 32),
("rvalid", 1),
("rdata", 32),
]
class OBI2Wishbone(Module):
def __init__(self, obi, wb):
addr = Signal.like(obi.addr)
be = Signal.like(obi.be)
we = Signal.like(obi.we)
wdata = Signal.like(obi.wdata)
self.submodules.fsm = fsm = FSM(reset_state="IDLE")
fsm.act("IDLE",
# On OBI request:
If(obi.req,
# Drive Wishbone bus from OBI bus.
wb.adr.eq(obi.addr[2:32]),
wb.stb.eq( 1),
wb.dat_w.eq( obi.wdata),
wb.cyc.eq( 1),
wb.sel.eq( obi.be),
wb.we.eq( obi.we),
# Store OBI bus values.
NextValue(addr, obi.addr),
NextValue(be, obi.be),
NextValue(we, obi.we),
NextValue(wdata, obi.wdata),
# Now we need to wait Wishbone Ack.
NextState("ACK")
),
obi.gnt.eq(1), # Always ack OBI request in Idle.
)
fsm.act("ACK",
# Drive Wishbone bus from stored OBI bus values.
wb.adr.eq(addr[2:32]),
wb.stb.eq( 1),
wb.dat_w.eq( wdata),
wb.cyc.eq( 1),
wb.sel.eq( be),
wb.we.eq( we),
# On Wishbone Ack:
If(wb.ack,
# Generate OBI response.
obi.rvalid.eq(1),
obi.rdata.eq(wb.dat_r),
# Return to Idle.
NextState("IDLE")
)
)
class Ibex(CPU):
name = "ibex"
human_name = "Ibex"
variants = CPU_VARIANTS
data_width = 32
endianness = "little"
gcc_triple = CPU_GCC_TRIPLE_RISCV32
linker_output_format = "elf32-littleriscv"
nop = "nop"
io_regions = {0x80000000: 0x80000000} # origin, length
@property
def gcc_flags(self):
flags = GCC_FLAGS[self.variant]
flags += "-D__ibex__ "
return flags
def __init__(self, platform, variant="standard"):
self.platform = platform
self.variant = variant
self.reset = Signal()
self.ibus = wishbone.Interface()
self.dbus = wishbone.Interface()
self.periph_buses = [self.ibus, self.dbus]
self.memory_buses = []
ibus = Record(obi_layout)
dbus = Record(obi_layout)
self.submodules.ibus_conv = OBI2Wishbone(ibus, self.ibus)
self.submodules.dbus_conv = OBI2Wishbone(dbus, self.dbus)
self.comb += [
ibus.we.eq(0),
ibus.be.eq(1111),
]
class Open(Signal): pass
self.cpu_params = dict(
# Configuration
p_RegFile = 1, # RegFileFPGA
i_test_en_i = 0,
i_hart_id_i = 0,
# Clk/Rst
i_clk_i = ClockSignal(),
i_rst_ni = ~ResetSignal(),
# Instruction bus
o_instr_req_o = ibus.req,
i_instr_gnt_i = ibus.gnt,
i_instr_rvalid_i = ibus.rvalid,
o_instr_addr_o = ibus.addr,
i_instr_rdata_i = ibus.rdata,
i_instr_err_i = 0,
# Data bus
o_data_req_o = dbus.req,
i_data_gnt_i = dbus.gnt,
i_data_rvalid_i = dbus.rvalid,
o_data_we_o = dbus.we,
o_data_be_o = dbus.be,
o_data_addr_o = dbus.addr,
o_data_wdata_o = dbus.wdata,
i_data_rdata_i = dbus.rdata,
i_data_err_i = 0,
# Interrupts
i_irq_software_i = 0,
i_irq_timer_i = 0,
i_irq_external_i = 0,
i_irq_fast_i = 0,
i_irq_nm_i = 0,
# Debug
i_debug_req_i = 0,
# Control/Status
i_fetch_enable_i = 1,
o_alert_minor_o = Open(),
o_alert_major_o = Open(),
o_core_sleep_o = Open()
)
# Add verilog sources
self.add_sources(platform)
@staticmethod
def add_sources(platform):
# FIXME: Create pythondata-cpu-ibex.
os.system("git clone https://github.com/lowRISC/ibex")
os.system("git clone https://github.com/lowRISC/opentitan")
platform.add_sources(os.path.join("ibex", "rtl"),
"ibex_pkg.sv",
"ibex_alu.sv",
"ibex_compressed_decoder.sv",
"ibex_controller.sv",
"ibex_counter.sv",
"ibex_cs_registers.sv",
"ibex_csr.sv",
"ibex_decoder.sv",
"ibex_ex_block.sv",
"ibex_id_stage.sv",
"ibex_if_stage.sv",
"ibex_load_store_unit.sv",
"ibex_multdiv_slow.sv",
"ibex_multdiv_fast.sv",
"ibex_prefetch_buffer.sv",
"ibex_fetch_fifo.sv",
"ibex_register_file_fpga.sv",
"ibex_wb_stage.sv",
"ibex_core.sv",
)
platform.add_source(os.path.join("ibex", "syn", "rtl", "prim_clock_gating.v"))
platform.add_sources(os.path.join("opentitan", "hw", "ip", "prim", "rtl"),
"prim_alert_pkg.sv",
"prim_assert.sv"
)
platform.add_verilog_include_path(os.path.join("opentitan", "hw", "ip", "prim", "rtl"))
platform.add_verilog_include_path(os.path.join("ibex", "dv", "fcov"))
def set_reset_address(self, reset_address):
assert not hasattr(self, "reset_address")
self.reset_address = reset_address
self.cpu_params.update(i_boot_addr_i=Signal(32, reset=reset_address))
def do_finalize(self):
assert hasattr(self, "reset_address")
self.specials += Instance("ibex_core", **self.cpu_params)

View File

@ -0,0 +1,75 @@
#define MIE_MEIE 0x800
.global _start
_start:
j reset_vector
reset_vector:
la sp, _fstack
la t0, trap_vector
csrw mtvec, t0
// initialize .data
la t0, _fdata
la t1, _edata
la t2, _fdata_rom
1: beq t0, t1, 2f
lw t3, 0(t2)
sw t3, 0(t0)
addi t0, t0, 4
addi t2, t2, 4
j 1b
2:
// initialize .bss
la t0, _fbss
la t1, _ebss
1: beq t0, t1, 3f
sw zero, 0(t0)
addi t0, t0, 4
j 1b
3:
// enable external interrupts
li t0, MIE_MEIE
csrs mie, t0
call main
1: j 1b
trap_vector:
addi sp, sp, -16*4
sw ra, 0*4(sp)
sw t0, 1*4(sp)
sw t1, 2*4(sp)
sw t2, 3*4(sp)
sw a0, 4*4(sp)
sw a1, 5*4(sp)
sw a2, 6*4(sp)
sw a3, 7*4(sp)
sw a4, 8*4(sp)
sw a5, 9*4(sp)
sw a6, 10*4(sp)
sw a7, 11*4(sp)
sw t3, 12*4(sp)
sw t4, 13*4(sp)
sw t5, 14*4(sp)
sw t6, 15*4(sp)
call isr
lw ra, 0*4(sp)
lw t0, 1*4(sp)
lw t1, 2*4(sp)
lw t2, 3*4(sp)
lw a0, 4*4(sp)
lw a1, 5*4(sp)
lw a2, 6*4(sp)
lw a3, 7*4(sp)
lw a4, 8*4(sp)
lw a5, 9*4(sp)
lw a6, 10*4(sp)
lw a7, 11*4(sp)
lw t3, 12*4(sp)
lw t4, 13*4(sp)
lw t5, 14*4(sp)
lw t6, 15*4(sp)
addi sp, sp, 16*4
mret

View File

@ -0,0 +1,4 @@
#ifndef __IRQ_H
#define __IRQ_H
#endif /* __IRQ_H */

View File

@ -0,0 +1,19 @@
#ifndef __SYSTEM_H
#define __SYSTEM_H
#ifdef __cplusplus
extern "C" {
#endif
__attribute__((unused)) static void flush_cpu_icache(void){}; /* No instruction cache */
__attribute__((unused)) static void flush_cpu_dcache(void){}; /* No instruction cache */
void flush_l2_cache(void);
void busy_wait(unsigned int ms);
void busy_wait_us(unsigned int us);
#ifdef __cplusplus
}
#endif
#endif /* __SYSTEM_H */

View File

@ -15,7 +15,8 @@ from litex import get_data_mod
from litex.soc.interconnect import wishbone
from litex.soc.cores.cpu import CPU
CPU_VARIANTS = ["standard", "standard+fpu", "linux", "linux+fpu"]
CPU_VARIANTS = ["standard", "standard+fpu", "linux", "linux+fpu",
"linux+smp", "linux+smp+fpu"]
class MOR1KX(CPU):
@ -113,6 +114,11 @@ class MOR1KX(CPU):
p_DBUS_WB_TYPE = "B3_REGISTERED_FEEDBACK",
)
if "smp" in variant:
cpu_args.update(
p_OPTION_RF_NUM_SHADOW_GPR = 1,
)
if "fpu" in variant:
cpu_args.update(
p_FEATURE_FPU = "ENABLED",

View File

@ -49,8 +49,8 @@ GCC_FLAGS = {
# imacfd
"minimal": "-march=rv32i -mabi=ilp32",
"minimal+debug": "-march=rv32i -mabi=ilp32",
"lite": "-march=rv32i -mabi=ilp32",
"lite+debug": "-march=rv32i -mabi=ilp32",
"lite": "-march=rv32im -mabi=ilp32",
"lite+debug": "-march=rv32im -mabi=ilp32",
"standard": "-march=rv32im -mabi=ilp32",
"standard+debug": "-march=rv32im -mabi=ilp32",
"imac": "-march=rv32imac -mabi=ilp32",
@ -265,6 +265,11 @@ class VexRiscv(CPU, AutoCSR):
vdir = get_data_mod("cpu", "vexriscv").data_location
platform.add_source(os.path.join(vdir, cpu_filename))
def add_soc_components(self, soc, soc_region_cls):
if "debug" in self.variant:
soc.bus.add_slave("vexriscv_debug", self.debug_bus, region=soc_region_cls(origin=0xf00f0000, size=0x100, cached=False))
def use_external_variant(self, variant_filename):
self.external_variant = True
self.platform.add_source(variant_filename)

View File

@ -37,30 +37,33 @@ class VexRiscvSMP(CPU):
nop = "nop"
io_regions = {0x80000000: 0x80000000} # origin, length
cpu_count = 1
dcache_size = 4096
icache_size = 4096
dcache_ways = 1
icache_ways = 1
coherent_dma = False
litedram_width = 32
dcache_width = 32
icache_width = 32
aes_instruction = False
cpu_count = 1
dcache_size = 4096
icache_size = 4096
dcache_ways = 1
icache_ways = 1
coherent_dma = False
litedram_width = 32
dcache_width = 32
icache_width = 32
aes_instruction = False
out_of_order_decoder = True
wishbone_memory = False
@staticmethod
def args_fill(parser):
parser.add_argument("--cpu-count", default=1, help="Number of CPU(s) in the cluster.", type=int)
parser.add_argument("--with-coherent-dma", action='store_true', help="Enable Coherent DMA Slave interface.")
parser.add_argument("--without-coherent-dma", action='store_true', help="Disable Coherent DMA Slave interface.")
parser.add_argument("--dcache-width", default=None, help="L1 data cache bus width.")
parser.add_argument("--icache-width", default=None, help="L1 instruction cache bus width.")
parser.add_argument("--dcache-size", default=None, help="L1 data cache size in byte per CPU.")
parser.add_argument("--dcache-ways", default=None, help="L1 data cache ways per CPU.")
parser.add_argument("--icache-size", default=None, help="L1 instruction cache size in byte per CPU.")
parser.add_argument("--icache-ways", default=None, help="L1 instruction cache ways per CPU")
parser.add_argument("--aes-instruction", default=None, help="Enable AES instruction acceleration.")
parser.add_argument("--cpu-count", default=1, help="Number of CPU(s) in the cluster.", type=int)
parser.add_argument("--with-coherent-dma", action="store_true", help="Enable Coherent DMA Slave interface.")
parser.add_argument("--without-coherent-dma", action="store_true", help="Disable Coherent DMA Slave interface.")
parser.add_argument("--dcache-width", default=None, help="L1 data cache bus width.")
parser.add_argument("--icache-width", default=None, help="L1 instruction cache bus width.")
parser.add_argument("--dcache-size", default=None, help="L1 data cache size in byte per CPU.")
parser.add_argument("--dcache-ways", default=None, help="L1 data cache ways per CPU.")
parser.add_argument("--icache-size", default=None, help="L1 instruction cache size in byte per CPU.")
parser.add_argument("--icache-ways", default=None, help="L1 instruction cache ways per CPU")
parser.add_argument("--aes-instruction", default=None, help="Enable AES instruction acceleration.")
parser.add_argument("--without-out-of-order-decoder", action="store_true", help="Reduce area at cost of peripheral access speed")
parser.add_argument("--with-wishbone-memory" , action="store_true", help="Disable native LiteDRAM interface")
@staticmethod
def args_read(args):
@ -73,15 +76,18 @@ class VexRiscvSMP(CPU):
VexRiscvSMP.dcache_ways = 2
VexRiscvSMP.icache_ways = 2
VexRiscvSMP.coherent_dma = True
if(args.with_coherent_dma): VexRiscvSMP.coherent_dma = bool(True)
if(args.without_coherent_dma): VexRiscvSMP.coherent_dma = bool(False)
if(args.dcache_width): VexRiscvSMP.dcache_width = int(args.dcache_width)
if(args.icache_width): VexRiscvSMP.icache_width = int(args.icache_width)
if(args.dcache_size): VexRiscvSMP.dcache_size = int(args.dcache_size)
if(args.icache_size): VexRiscvSMP.icache_size = int(args.icache_size)
if(args.dcache_ways): VexRiscvSMP.dcache_ways = int(args.dcache_ways)
if(args.icache_ways): VexRiscvSMP.icache_ways = int(args.icache_ways)
if(args.aes_instruction): VexRiscvSMP.aes_instruction = bool(args.aes_instruction)
if(args.with_coherent_dma): VexRiscvSMP.coherent_dma = bool(True)
if(args.without_coherent_dma): VexRiscvSMP.coherent_dma = bool(False)
if(args.dcache_width): VexRiscvSMP.dcache_width = int(args.dcache_width)
if(args.icache_width): VexRiscvSMP.icache_width = int(args.icache_width)
if(args.dcache_size): VexRiscvSMP.dcache_size = int(args.dcache_size)
if(args.icache_size): VexRiscvSMP.icache_size = int(args.icache_size)
if(args.dcache_ways): VexRiscvSMP.dcache_ways = int(args.dcache_ways)
if(args.icache_ways): VexRiscvSMP.icache_ways = int(args.icache_ways)
if(args.aes_instruction): VexRiscvSMP.aes_instruction = bool(args.aes_instruction)
if(args.without_out_of_order_decoder): VexRiscvSMP.out_of_order_decoder = False
if(args.with_wishbone_memory): VexRiscvSMP.wishbone_memory = True
@property
def mem_map(self):
@ -103,6 +109,7 @@ class VexRiscvSMP(CPU):
@staticmethod
def generate_cluster_name():
ldw = f"Ldw{VexRiscvSMP.litedram_width}"
VexRiscvSMP.cluster_name = f"VexRiscvLitexSmpCluster_" \
f"Cc{VexRiscvSMP.cpu_count}" \
"_" \
@ -113,10 +120,11 @@ class VexRiscvSMP(CPU):
f"Dw{VexRiscvSMP.dcache_width}" \
f"Ds{VexRiscvSMP.dcache_size}" \
f"Dy{VexRiscvSMP.dcache_ways}" \
"_" \
f"Ldw{VexRiscvSMP.litedram_width}" \
f"{'_Cdma' if VexRiscvSMP.coherent_dma else ''}" \
f"{'_Aes' if VexRiscvSMP.aes_instruction else ''}"
f"{'_'+ldw if not VexRiscvSMP.wishbone_memory else ''}" \
f"{'_Cdma' if VexRiscvSMP.coherent_dma else ''}" \
f"{'_Aes' if VexRiscvSMP.aes_instruction else ''}" \
f"{'_Ood' if VexRiscvSMP.out_of_order_decoder else ''}" \
f"{'_Wm' if VexRiscvSMP.wishbone_memory else ''}"
@staticmethod
def generate_default_configs():
@ -192,11 +200,14 @@ class VexRiscvSMP(CPU):
gen_args.append(f"--icache-ways={VexRiscvSMP.icache_ways}")
gen_args.append(f"--litedram-width={VexRiscvSMP.litedram_width}")
gen_args.append(f"--aes-instruction={VexRiscvSMP.aes_instruction}")
gen_args.append(f"--out-of-order-decoder={VexRiscvSMP.out_of_order_decoder}")
gen_args.append(f"--wishbone-memory={VexRiscvSMP.wishbone_memory}")
gen_args.append(f"--netlist-name={VexRiscvSMP.cluster_name}")
gen_args.append(f"--netlist-directory={vdir}")
cmd = 'cd {path} && sbt "runMain vexriscv.demo.smp.VexRiscvLitexSmpClusterCmdGen {args}"'.format(path=os.path.join(vdir, "ext", "VexRiscv"), args=" ".join(gen_args))
os.system(cmd)
if os.system(cmd) != 0:
raise OSError('Failed to run sbt')
def __init__(self, platform, variant):
self.platform = platform
@ -324,37 +335,38 @@ class VexRiscvSMP(CPU):
VexRiscvSMP.generate_cluster_name()
from litedram.common import LiteDRAMNativePort
ibus = LiteDRAMNativePort(mode="both", address_width=32, data_width=VexRiscvSMP.litedram_width)
dbus = LiteDRAMNativePort(mode="both", address_width=32, data_width=VexRiscvSMP.litedram_width)
self.memory_buses.append(ibus)
self.memory_buses.append(dbus)
self.cpu_params.update(
# Instruction Memory Bus (Master)
o_iBridge_dram_cmd_valid = ibus.cmd.valid,
i_iBridge_dram_cmd_ready = ibus.cmd.ready,
o_iBridge_dram_cmd_payload_we = ibus.cmd.we,
o_iBridge_dram_cmd_payload_addr = ibus.cmd.addr,
o_iBridge_dram_wdata_valid = ibus.wdata.valid,
i_iBridge_dram_wdata_ready = ibus.wdata.ready,
o_iBridge_dram_wdata_payload_data = ibus.wdata.data,
o_iBridge_dram_wdata_payload_we = ibus.wdata.we,
i_iBridge_dram_rdata_valid = ibus.rdata.valid,
o_iBridge_dram_rdata_ready = ibus.rdata.ready,
i_iBridge_dram_rdata_payload_data = ibus.rdata.data,
if(not VexRiscvSMP.wishbone_memory):
ibus = LiteDRAMNativePort(mode="both", address_width=32, data_width=VexRiscvSMP.litedram_width)
dbus = LiteDRAMNativePort(mode="both", address_width=32, data_width=VexRiscvSMP.litedram_width)
self.memory_buses.append(ibus)
self.memory_buses.append(dbus)
self.cpu_params.update(
# Instruction Memory Bus (Master)
o_iBridge_dram_cmd_valid = ibus.cmd.valid,
i_iBridge_dram_cmd_ready = ibus.cmd.ready,
o_iBridge_dram_cmd_payload_we = ibus.cmd.we,
o_iBridge_dram_cmd_payload_addr = ibus.cmd.addr,
o_iBridge_dram_wdata_valid = ibus.wdata.valid,
i_iBridge_dram_wdata_ready = ibus.wdata.ready,
o_iBridge_dram_wdata_payload_data = ibus.wdata.data,
o_iBridge_dram_wdata_payload_we = ibus.wdata.we,
i_iBridge_dram_rdata_valid = ibus.rdata.valid,
o_iBridge_dram_rdata_ready = ibus.rdata.ready,
i_iBridge_dram_rdata_payload_data = ibus.rdata.data,
# Data Memory Bus (Master)
o_dBridge_dram_cmd_valid = dbus.cmd.valid,
i_dBridge_dram_cmd_ready = dbus.cmd.ready,
o_dBridge_dram_cmd_payload_we = dbus.cmd.we,
o_dBridge_dram_cmd_payload_addr = dbus.cmd.addr,
o_dBridge_dram_wdata_valid = dbus.wdata.valid,
i_dBridge_dram_wdata_ready = dbus.wdata.ready,
o_dBridge_dram_wdata_payload_data = dbus.wdata.data,
o_dBridge_dram_wdata_payload_we = dbus.wdata.we,
i_dBridge_dram_rdata_valid = dbus.rdata.valid,
o_dBridge_dram_rdata_ready = dbus.rdata.ready,
i_dBridge_dram_rdata_payload_data = dbus.rdata.data,
)
# Data Memory Bus (Master)
o_dBridge_dram_cmd_valid = dbus.cmd.valid,
i_dBridge_dram_cmd_ready = dbus.cmd.ready,
o_dBridge_dram_cmd_payload_we = dbus.cmd.we,
o_dBridge_dram_cmd_payload_addr = dbus.cmd.addr,
o_dBridge_dram_wdata_valid = dbus.wdata.valid,
i_dBridge_dram_wdata_ready = dbus.wdata.ready,
o_dBridge_dram_wdata_payload_data = dbus.wdata.data,
o_dBridge_dram_wdata_payload_we = dbus.wdata.we,
i_dBridge_dram_rdata_valid = dbus.rdata.valid,
o_dBridge_dram_rdata_ready = dbus.rdata.ready,
i_dBridge_dram_rdata_payload_data = dbus.rdata.data,
)
def do_finalize(self):
assert hasattr(self, "reset_address")
@ -362,3 +374,4 @@ class VexRiscvSMP(CPU):
# Add verilog sources
self.add_sources(self.platform)

View File

@ -10,6 +10,8 @@ from migen.genlib.cdc import MultiReg
from litex.soc.interconnect.csr import *
from litex.soc.interconnect.csr_eventmanager import *
# Helpers ------------------------------------------------------------------------------------------
def _to_signal(obj):
@ -18,11 +20,34 @@ def _to_signal(obj):
# GPIO Input ---------------------------------------------------------------------------------------
class GPIOIn(Module, AutoCSR):
def __init__(self, pads):
"""GPIO Input
Provides a GPIO Input peripheral. An optional IRQ dict can be passed to add rising or falling
interrupts to pads.
Ex: pads=Signal(8), irqs={} : 8-bit Input, No IRQ.
pads=Signal(8), irqs={0: "rise", 7: "fall"}: 8-bit Input, rising IRQ on 0, falling IRQ on 1.
"""
def __init__(self, pads, irqs={}):
pads = _to_signal(pads)
# Inputs
self._in = CSRStatus(len(pads), description="GPIO Input(s) Status.")
self.specials += MultiReg(pads, self._in.status)
# IRQs
if len(irqs):
self.submodules.ev = EventManager()
for n, irq_type in irqs.items():
assert irq_type in ["fall", "falling", "rise", "rising"]
assert len(pads) > n
name = f"i{n}"
if irq_type in ["rise", "rising"]:
setattr(self.ev, f"i{n}", EventSourcePulse())
if irq_type in ["fall", "falling"]:
setattr(self.ev, f"i{n}", EventSourceProcess())
self.comb += getattr(self.ev, f"i{n}").trigger.eq(pads[n])
# GPIO Output --------------------------------------------------------------------------------------
class GPIOOut(Module, AutoCSR):

View File

@ -22,20 +22,23 @@ class JTAGAtlantic(Module):
self.specials += Instance("alt_jtag_atlantic",
# Parameters
p_LOG2_RXFIFO_DEPTH="5", # FIXME: expose?
p_LOG2_TXFIFO_DEPTH="5", # FIXME: expose?
p_SLD_AUTO_INSTANCE_INDEX="YES",
p_LOG2_RXFIFO_DEPTH = "5", # FIXME: expose?
p_LOG2_TXFIFO_DEPTH = "5", # FIXME: expose?
p_SLD_AUTO_INSTANCE_INDEX = "YES",
# Clk/Rst
i_clk=ClockSignal("sys"),
i_rst_n=~ResetSignal("sys"),
i_clk = ClockSignal("sys"),
i_rst_n = ~ResetSignal("sys"),
# TX
i_r_dat=sink.data,
i_r_val=sink.valid,
o_r_ena=sink.ready,
i_r_dat = sink.data,
i_r_val = sink.valid,
o_r_ena = sink.ready,
# RX
o_t_dat=source.data,
i_t_dav=source.ready,
o_t_ena=source.valid,
o_t_dat = source.data,
i_t_dav = source.ready,
o_t_ena = source.valid,
)
# Xilinx JTAG --------------------------------------------------------------------------------------
@ -54,20 +57,19 @@ class XilinxJTAG(Module):
# # #
self.specials += \
Instance(primitive,
p_JTAG_CHAIN=chain,
self.specials += Instance(primitive,
p_JTAG_CHAIN = chain,
o_RESET=self.reset,
o_CAPTURE=self.capture,
o_SHIFT=self.shift,
o_UPDATE=self.update,
o_RESET = self.reset,
o_CAPTURE = self.capture,
o_SHIFT = self.shift,
o_UPDATE = self.update,
o_TCK=self.tck,
o_TMS=self.tms,
o_TDI=self.tdi,
i_TDO=self.tdo,
)
o_TCK = self.tck,
o_TMS = self.tms,
o_TDI = self.tdi,
i_TDO = self.tdo,
)
class S6JTAG(XilinxJTAG):
def __init__(self, *args, **kwargs):
@ -123,12 +125,12 @@ class JTAGPHY(Module):
jtag = USJTAG()
else:
raise NotImplementedError
self.submodules += jtag
self.submodules.jtag = jtag
# JTAG clock domain ------------------------------------------------------------------------
self.clock_domains.cd_jtag = ClockDomain()
self.comb += ClockSignal("jtag").eq(jtag.tck)
self.specials += AsyncResetSynchronizer(self.cd_jtag, ResetSignal("sys"))
self.specials += AsyncResetSynchronizer(self.cd_jtag, ResetSignal(clock_domain))
# JTAG clock domain crossing ---------------------------------------------------------------
if clock_domain != "jtag":
@ -136,7 +138,8 @@ class JTAGPHY(Module):
tx_cdc = ClockDomainsRenamer({"write": clock_domain, "read": "jtag"})(tx_cdc)
rx_cdc = stream.AsyncFIFO([("data", data_width)], 4)
rx_cdc = ClockDomainsRenamer({"write": "jtag", "read": clock_domain})(rx_cdc)
self.submodules += tx_cdc, rx_cdc
self.submodules.tx_cdc = tx_cdc
self.submodules.rx_cdc = rx_cdc
self.comb += [
sink.connect(tx_cdc.sink),
rx_cdc.source.connect(source)

View File

@ -273,10 +273,9 @@ class Stream2Wishbone(Module):
bytes_count_done = (bytes_count == (data_width//8 - 1))
words_count_done = (words_count == (length - 1))
fsm = ResetInserter()(FSM(reset_state="RECEIVE-CMD"))
timer = WaitTimer(int(100e-3*clk_freq))
self.submodules.fsm = fsm = ResetInserter()(FSM(reset_state="RECEIVE-CMD"))
self.submodules.timer = timer = WaitTimer(int(100e-3*clk_freq))
self.comb += timer.wait.eq(~fsm.ongoing("RECEIVE-CMD"))
self.submodules += fsm, timer
self.comb += fsm.reset.eq(timer.done)
fsm.act("RECEIVE-CMD",
sink.ready.eq(1),
@ -378,12 +377,12 @@ class Stream2Wishbone(Module):
class UARTBone(Stream2Wishbone):
def __init__(self, pads, clk_freq, baudrate=115200, cd="sys"):
def __init__(self, phy, clk_freq, cd="sys"):
if cd == "sys":
self.submodules.phy = RS232PHY(pads, clk_freq, baudrate)
self.submodules.phy = phy
Stream2Wishbone.__init__(self, self.phy, clk_freq=clk_freq)
else:
self.submodules.phy = ClockDomainsRenamer(cd)(RS232PHY(pads, clk_freq, baudrate))
self.submodules.phy = ClockDomainsRenamer(cd)(phy)
self.submodules.tx_cdc = stream.ClockDomainCrossing([("data", 8)], cd_from="sys", cd_to=cd)
self.submodules.rx_cdc = stream.ClockDomainCrossing([("data", 8)], cd_from=cd, cd_to="sys")
self.comb += self.phy.source.connect(self.rx_cdc.sink)
@ -392,7 +391,10 @@ class UARTBone(Stream2Wishbone):
self.comb += self.rx_cdc.source.connect(self.sink)
self.comb += self.source.connect(self.tx_cdc.sink)
class UARTWishboneBridge(UARTBone): pass
class UARTWishboneBridge(UARTBone):
def __init__(self, pads, clk_freq, baudrate=115200, cd="sys"):
self.submodules.phy = RS232PHY(pads, clk_freq, baudrate)
UARTBone.__init__(self, self.phy, clk_freq, cd)
# UART Multiplexer ---------------------------------------------------------------------------------

View File

@ -28,6 +28,7 @@ offline_skin_js_path = "https://wavedrom.com/skins/default.js"
offline_wavedrom_js_path = "https://wavedrom.com/WaveDrom.js"
html_theme = 'alabaster'
html_static_path = ['_static']
master_doc = 'index'
"""
def generate_svd(soc, buildpath, filename=None, name="soc", **kwargs):

View File

@ -64,6 +64,9 @@ def get_cpu_mak(cpu, compile_software):
r = None
if not isinstance(triple, tuple):
triple = (triple,)
override = os.getenv("LITEX_ENV_CC_TRIPLE")
if override:
triple = (override,) + triple
p = get_platform()
for i in range(len(triple)):
t = triple[i]
@ -238,7 +241,7 @@ def get_csr_header(regions, constants, csr_base=None, with_access_functions=True
size = str(field.size)
r += "#define CSR_"+name.upper()+"_"+csr.name.upper()+"_"+field.name.upper()+"_OFFSET "+offset+"\n"
r += "#define CSR_"+name.upper()+"_"+csr.name.upper()+"_"+field.name.upper()+"_SIZE "+size+"\n"
if with_access_functions:
if with_access_functions and csr.size <= 32: # FIXME: Implement extract/read functions for csr.size > 32-bit.
reg_name = name + "_" + csr.name.lower()
field_name = reg_name + "_" + field.name.lower()
r += "static inline uint32_t " + field_name + "_extract(uint32_t oldword) {\n"

View File

@ -939,7 +939,8 @@ class SoC(Module):
# Connect SoCController's reset to CRG's reset if presents.
if hasattr(self, "ctrl") and hasattr(self, "crg"):
if hasattr(self.ctrl, "_reset") and hasattr(self.crg, "rst"):
self.comb += self.crg.rst.eq(self.ctrl._reset.re)
if isinstance(self.crg.rst, Signal):
self.comb += self.crg.rst.eq(self.ctrl._reset.re)
# SoC CSR bridge ---------------------------------------------------------------------------
# FIXME: for now, use registered CSR bridge when SDRAM is present; find the best compromise.
@ -1115,25 +1116,27 @@ class LiteXSoC(SoC):
# Model/Sim
elif name in ["model", "sim"]:
self.submodules.uart_phy = uart.RS232PHYModel(self.platform.request("serial"))
self.submodules.uart = ResetInserter()(uart.UART(self.uart_phy,
self.submodules.uart = uart.UART(self.uart_phy,
tx_fifo_depth = fifo_depth,
rx_fifo_depth = fifo_depth))
rx_fifo_depth = fifo_depth)
# JTAG Atlantic
elif name in ["jtag_atlantic"]:
from litex.soc.cores.jtag import JTAGAtlantic
self.submodules.uart_phy = JTAGAtlantic()
self.submodules.uart = ResetInserter()(uart.UART(self.uart_phy,
self.submodules.uart = uart.UART(self.uart_phy,
tx_fifo_depth = fifo_depth,
rx_fifo_depth = fifo_depth))
rx_fifo_depth = fifo_depth)
# JTAG UART
elif name in ["jtag_uart"]:
from litex.soc.cores.jtag import JTAGPHY
self.submodules.uart_phy = JTAGPHY(device=self.platform.device)
self.submodules.uart = ResetInserter()(uart.UART(self.uart_phy,
self.clock_domains.cd_sys_jtag = ClockDomain() # Run JTAG-UART in sys_jtag clock domain similar to
self.comb += self.cd_sys_jtag.clk.eq(ClockSignal("sys")) # sys clock domain but with rst disconnected.
self.submodules.uart_phy = JTAGPHY(device=self.platform.device, clock_domain="sys_jtag")
self.submodules.uart = uart.UART(self.uart_phy,
tx_fifo_depth = fifo_depth,
rx_fifo_depth = fifo_depth))
rx_fifo_depth = fifo_depth)
# USB ACM (with ValentyUSB core)
elif name in ["usb_acm"]:
@ -1141,7 +1144,9 @@ class LiteXSoC(SoC):
import valentyusb.usbcore.cpu.cdc_eptri as cdc_eptri
usb_pads = self.platform.request("usb")
usb_iobuf = usbio.IoBuf(usb_pads.d_p, usb_pads.d_n, usb_pads.pullup)
self.submodules.uart = cdc_eptri.CDCUsb(usb_iobuf)
self.clock_domains.cd_sys_usb = ClockDomain() # Run USB ACM in sys_usb clock domain similar to
self.comb += self.cd_sys_usb.clk.eq(ClockSignal("sys")) # sys clock domain but with rst disconnected.
self.submodules.uart = ClockDomainsRenamer("sys_usb")(cdc_eptri.CDCUsb(usb_iobuf))
# Classic UART
else:
@ -1149,9 +1154,9 @@ class LiteXSoC(SoC):
pads = self.platform.request(name),
clk_freq = self.sys_clk_freq,
baudrate = baudrate)
self.submodules.uart = ResetInserter()(uart.UART(self.uart_phy,
self.submodules.uart = uart.UART(self.uart_phy,
tx_fifo_depth = fifo_depth,
rx_fifo_depth = fifo_depth))
rx_fifo_depth = fifo_depth)
self.csr.add("uart_phy", use_loc_if_exists=True)
self.csr.add("uart", use_loc_if_exists=True)
@ -1163,13 +1168,21 @@ class LiteXSoC(SoC):
# Add UARTbone ---------------------------------------------------------------------------------
def add_uartbone(self, name="serial", clk_freq=None, baudrate=115200, cd="sys"):
from litex.soc.cores import uart
self.submodules.uartbone = uart.UARTBone(
pads = self.platform.request(name),
clk_freq = clk_freq if clk_freq is not None else self.sys_clk_freq,
baudrate = baudrate,
cd = cd)
if clk_freq is None:
clk_freq = self.sys_clk_freq
self.submodules.uartbone_phy = uart.UARTPHY(self.platform.request(name), clk_freq, baudrate)
self.csr.add("uartbone_phy")
self.submodules.uartbone = uart.UARTBone(phy=self.uartbone_phy, clk_freq=clk_freq, cd=cd)
self.bus.add_master(name="uartbone", master=self.uartbone.wishbone)
# Add JTAGbone ---------------------------------------------------------------------------------
def add_jtagbone(self):
from litex.soc.cores import uart
from litex.soc.cores.jtag import JTAGPHY
self.submodules.jtagbone_phy = JTAGPHY(device=self.platform.device)
self.submodules.jtagbone = uart.UARTBone(phy=self.jtagbone_phy, clk_freq=self.sys_clk_freq)
self.bus.add_master(name="jtagbone", master=self.jtagbone.wishbone)
# Add SDRAM ------------------------------------------------------------------------------------
def add_sdram(self, name, phy, module, origin, size=None, with_bist=False, with_soc_interconnect=True,
l2_cache_size = 8192,
@ -1467,7 +1480,7 @@ class LiteXSoC(SoC):
sdcard_pads = self.platform.request(name)
# Core
self.submodules.sdphy = SDPHY(sdcard_pads, self.platform.device, self.clk_freq)
self.submodules.sdphy = SDPHY(sdcard_pads, self.platform.device, self.clk_freq, cmd_timeout=10e-1, data_timeout=10e-1)
self.submodules.sdcore = SDCore(self.sdphy)
self.csr.add("sdphy", use_loc_if_exists=True)
self.csr.add("sdcore", use_loc_if_exists=True)
@ -1561,7 +1574,7 @@ class LiteXSoC(SoC):
self.sata_phy.crg.cd_sata_rx.clk)
# Add PCIe -------------------------------------------------------------------------------------
def add_pcie(self, name="pcie", phy=None, ndmas=0):
def add_pcie(self, name="pcie", phy=None, ndmas=0, max_pending_requests=8):
assert self.csr.data_width == 32
assert not hasattr(self, f"{name}_endpoint")
@ -1571,7 +1584,7 @@ class LiteXSoC(SoC):
from litepcie.frontend.wishbone import LitePCIeWishboneMaster
# Endpoint
endpoint = LitePCIeEndpoint(phy, max_pending_requests=8)
endpoint = LitePCIeEndpoint(phy, max_pending_requests=max_pending_requests)
setattr(self.submodules, f"{name}_endpoint", endpoint)
# MMAP

View File

@ -258,10 +258,13 @@ class AXILiteInterface:
# AXI Stream Definition ----------------------------------------------------------------------------
class AXIStreamInterface(stream.Endpoint):
def __init__(self, data_width=32, user_width=0):
def __init__(self, data_width=32, keep_width=0, user_width=0):
self.data_width = data_width
self.keep_width = keep_width
self.user_width = user_width
payload_layout = [("data", data_width)]
if self.keep_width:
payload_layout += [("keep", keep_width)]
param_layout = []
if self.user_width:
param_layout += [("user", user_width)]
@ -274,6 +277,8 @@ class AXIStreamInterface(stream.Endpoint):
Subsignal("tready", Pins(1)),
Subsignal("tdata", Pins(self.data_width)),
]
if self.keep_width:
subsignals += [Subsignal("tkeep", Pins(self.keep_width))]
if self.user_width:
subsignals += [Subsignal("tuser", Pins(self.user_width))]
ios = [(bus_name , 0) + tuple(subsignals)]
@ -287,6 +292,8 @@ class AXIStreamInterface(stream.Endpoint):
r.append(self.ready.eq(pads.tready))
r.append(pads.tlast.eq(self.last))
r.append(pads.tdata.eq(self.data))
if self.keep_width:
r.append(pads.tkeep.eq(self.keep))
if self.user_width:
r.append(pads.tuser.eq(self.user))
if mode == "slave":
@ -294,6 +301,8 @@ class AXIStreamInterface(stream.Endpoint):
r.append(pads.tready.eq(self.ready))
r.append(self.last.eq(pads.tlast))
r.append(self.data.eq(pads.tdata))
if self.keep_width:
r.append(self.keep.eq(pads.tkeep))
if self.user_width:
r.append(self.user.eq(pads.tuser))
return r

View File

@ -26,7 +26,6 @@
#include "jsmn.h"
#include <progress.h>
#include <spiflash.h>
#include <libliteeth/udp.h>
#include <libliteeth/tftp.h>
@ -51,7 +50,7 @@ extern void boot_helper(unsigned long r1, unsigned long r2, unsigned long r3, un
static void __attribute__((noreturn)) boot(unsigned long r1, unsigned long r2, unsigned long r3, unsigned long addr)
{
printf("Executing booted program at 0x%08x\n\n", addr);
printf("Executing booted program at 0x%08lx\n\n", addr);
printf("--============= \e[1mLiftoff!\e[0m ===============--\n");
uart_sync();
#ifdef CONFIG_CPU_HAS_INTERRUPT
@ -109,7 +108,11 @@ static int check_ack(void)
timer0_en_write(0);
timer0_reload_write(0);
#ifndef CONFIG_DISABLE_DELAYS
timer0_load_write(CONFIG_CLOCK_FREQUENCY/4);
#else
timer0_load_write(0);
#endif
timer0_en_write(1);
timer0_update_value_write(1);
recognized = 0;
@ -213,7 +216,7 @@ int serialboot(void)
char *writepointer;
failed = 0;
writepointer = (char *) get_uint32(&frame.payload[0]);
writepointer = (char *)(uintptr_t) get_uint32(&frame.payload[0]);
for(i=4;i<frame.payload_length;i++)
*(writepointer++) = frame.payload[i];
if (frame.cmd == SFL_CMD_LOAD)
@ -229,31 +232,6 @@ int serialboot(void)
boot(0, 0, 0, addr);
break;
}
case SFL_CMD_FLASH: {
#if (defined CSR_SPIFLASH_BASE && defined SPIFLASH_PAGE_SIZE)
uint32_t addr;
failed = 0;
addr = get_uint32(&frame.payload[0]);
for (i = 4; i < frame.payload_length; i++) {
/* Erase page at sector boundaries before writing */
if ((addr & (SPIFLASH_SECTOR_SIZE - 1)) == 0) {
erase_flash_sector(addr);
}
write_to_flash(addr, &frame.payload[i], 1);
addr++;
}
uart_write(SFL_ACK_SUCCESS);
#endif
break;
}
case SFL_CMD_REBOOT:
#ifdef CSR_CTRL_RESET_ADDR
uart_write(SFL_ACK_SUCCESS);
ctrl_reset_write(1);
#endif
break;
default:
failed++;
if(failed == MAX_FAILED) {
@ -299,7 +277,7 @@ static int copy_file_from_tftp_to_ram(unsigned int ip, unsigned short server_por
const char *filename, char *buffer)
{
int size;
printf("Copying %s to 0x%08x... ", filename, buffer);
printf("Copying %s to %p... ", filename, buffer);
size = tftp_get(ip, server_port, filename, buffer);
if(size > 0)
printf("(%d bytes)", size);
@ -454,7 +432,7 @@ static int copy_image_from_flash_to_ram(unsigned int flash_address, unsigned lon
length = check_image_in_flash(flash_address);
if(length > 0) {
printf("Copying 0x%08x to 0x%08x (%d bytes)...\n", flash_address, ram_address, length);
printf("Copying 0x%08x to 0x%08lx (%d bytes)...\n", flash_address, ram_address, length);
offset = 0;
init_progression_bar(length);
while (length > 0) {
@ -526,7 +504,7 @@ static int copy_file_from_sdcard_to_ram(const char * filename, unsigned long ram
}
length = f_size(&file);
printf("Copying %s to 0x%08x (%d bytes)...\n", filename, ram_address, length);
printf("Copying %s to 0x%08lx (%d bytes)...\n", filename, ram_address, length);
init_progression_bar(length);
offset = 0;
for (;;) {
@ -701,7 +679,7 @@ static int copy_file_from_sata_to_ram(const char * filename, unsigned long ram_a
}
length = f_size(&file);
printf("Copying %s to 0x%08x (%d bytes)...\n", filename, ram_address, length);
printf("Copying %s to 0x%08lx (%d bytes)...\n", filename, ram_address, length);
init_progression_bar(length);
offset = 0;
for (;;) {

View File

@ -87,8 +87,8 @@ define_command(uptime, uptime_handler, "Uptime of the system since power-up", SY
static void crc_handler(int nb_params, char **params)
{
char *c;
unsigned int addr;
unsigned int length;
uintptr_t addr;
size_t length;
if (nb_params < 2) {
printf("crc <address> <length>");

View File

@ -40,7 +40,7 @@ static void i2c_write_handler(int nb_params, char **params)
}
if (nb_params - 1 > sizeof(write_params)) {
printf("Max data length is %d", sizeof(write_params));
printf("Max data length is %zu", sizeof(write_params));
return;
}
@ -98,7 +98,7 @@ static void i2c_read_handler(int nb_params, char **params)
return;
}
if (len > sizeof(buf)) {
printf("Max data count is %d", sizeof(buf));
printf("Max data count is %zu", sizeof(buf));
return;
}
@ -135,10 +135,10 @@ static void i2c_scan_handler(int nb_params, char **params)
printf(" 0 1 2 3 4 5 6 7 8 9 a b c d e f");
for (slave_addr = 0; slave_addr < 0x80; slave_addr++) {
if (slave_addr % 0x10 == 0) {
printf("\n0x%02x:", (slave_addr/0x10) * 0x10);
printf("\n0x%02x:", slave_addr & 0x70);
}
if (i2c_poll(slave_addr)) {
printf(" %02x");
printf(" %02x", slave_addr);
} else {
printf(" --");
}

View File

@ -25,7 +25,7 @@ void dump_bytes(unsigned int *ptr, int count, unsigned long addr)
(count > NUMBER_OF_BYTES_ON_A_LINE)?
NUMBER_OF_BYTES_ON_A_LINE : count;
printf("\n0x%08x ", addr);
printf("\n0x%08lx ", addr);
for (i = 0; i < line_bytes; i++)
printf("%02x ", *(unsigned char *)(data+i));

View File

@ -91,6 +91,7 @@ int main(int i, char **c)
uart_init();
#endif
#ifndef CONFIG_SIM_DISABLE_BIOS_PROMPT
printf("\n");
printf("\e[1m __ _ __ _ __\e[0m\n");
printf("\e[1m / / (_) /____ | |/_/\e[0m\n");
@ -140,6 +141,7 @@ int main(int i, char **c)
#endif
#endif
printf("\n");
#endif // CONFIG_SIM_DISABLE_BIOS_PROMPT
sdr_ok = 1;

View File

@ -150,10 +150,10 @@ void hist_init(void)
}
#endif
static void cread_add_char(char ichar, int insert, unsigned long *num,
unsigned long *eol_num, char *buf, unsigned long len)
static void cread_add_char(char ichar, int insert, unsigned int *num,
unsigned int *eol_num, char *buf, unsigned int len)
{
unsigned long wlen;
unsigned int wlen;
if (insert || *num == *eol_num) {
if (*eol_num > len - 1) {
@ -186,11 +186,11 @@ static void cread_add_char(char ichar, int insert, unsigned long *num,
int readline(char *buf, int len)
{
unsigned long num = 0;
unsigned long eol_num = 0;
unsigned long wlen;
unsigned int num = 0;
unsigned int eol_num = 0;
unsigned int wlen;
int insert = 1;
char ichar;
unsigned char ichar;
#ifndef TERM_NO_COMPLETE
char tmp;
@ -254,7 +254,7 @@ int readline(char *buf, int len)
wlen = eol_num - num - 1;
if (wlen) {
memmove(&buf[num], &buf[num+1], wlen);
putnstr(buf + num, (int)wlen);
putnstr(buf + num, wlen);
}
getcmd_putch(' ');
@ -286,7 +286,7 @@ int readline(char *buf, int len)
num--;
memmove(buf + num, buf + num + 1, wlen);
getcmd_putch(CTL_BACKSPACE);
putnstr(buf + num, (int)wlen);
putnstr(buf + num, wlen);
getcmd_putch(' ');
do {
getcmd_putch(CTL_BACKSPACE);
@ -298,7 +298,7 @@ int readline(char *buf, int len)
if (num < eol_num) {
wlen = eol_num - num;
memmove(buf + num, buf + num + 1, wlen);
putnstr(buf + num, (int)(wlen - 1));
putnstr(buf + num, wlen - 1);
getcmd_putch(' ');
do {
getcmd_putch(CTL_BACKSPACE);

View File

@ -72,7 +72,7 @@ struct esc_cmds {
#define REFRESH_TO_EOL() { \
if (num < eol_num) { \
wlen = eol_num - num; \
putnstr(buf + num, (int)wlen); \
putnstr(buf + num, wlen); \
num = eol_num; \
} \
}

View File

@ -19,8 +19,6 @@ struct sfl_frame {
#define SFL_CMD_ABORT 0x00
#define SFL_CMD_LOAD 0x01
#define SFL_CMD_JUMP 0x02
#define SFL_CMD_FLASH 0x04
#define SFL_CMD_REBOOT 0x05
/* Replies */
#define SFL_ACK_SUCCESS 'K'

View File

@ -6,8 +6,10 @@ This directory provides a minimal bare metal demo app that demonstrates how to e
[> Build
--------
Imagine you just build the Arty example design from LiteX-Boards, to build the demo app, run:
`$ litex_bare_metal_demo --build-path=build/arty/`
Imagine you just built the Arty example design from LiteX-Boards. Build the demo app as follows; where the build path is the path to your previously built Arty build directory:
```
litex_bare_metal_demo --build-path=build/arty/
```
[> Load
-------

View File

@ -12,7 +12,7 @@ from distutils.dir_util import copy_tree
def main():
parser = argparse.ArgumentParser(description="LiteX Bare Metal Demo App.")
parser.add_argument("--build-path", help="Target's build path.", required=True)
parser.add_argument("--build-path", help="Target's build path (ex build/board_name)", required=True)
args = parser.parse_args()
# Create demo directory
@ -23,7 +23,8 @@ def main():
copy_tree(src, "demo")
# Compile demo
os.system(f"export BUILD_DIR=../{args.build_path} && cd demo && make")
build_path = args.build_path if os.path.isabs(args.build_path) else os.path.join("..", args.build_path)
os.system(f"export BUILD_DIR={build_path} && cd demo && make")
# Copy demo.bin
os.system("cp demo/demo.bin ./")

View File

@ -24,7 +24,7 @@
#include <stdint.h>
# if __WORDSIZE == 64
# ifdef __LP64__
# define __PRI64_PREFIX "l"
# define __PRIPTR_PREFIX "l"
# else

View File

@ -65,7 +65,7 @@ static inline unsigned long lfsr(unsigned long bits, unsigned long prev)
0x20000029,
0x48000000,
0x80200003,
#if __WORDSIZE == 64
#ifdef __LP64__
0x100080000,
0x204000003,
0x500000000,

View File

@ -5,17 +5,21 @@
extern "C" {
#endif
#define ULONG_MAX 0xffffffff
#ifdef __LP64__
#define ULONG_MAX 18446744073709551615UL
#else
#define ULONG_MAX 4294967295UL
#endif
#define UINT_MAX 0xffffffff
#define INT_MIN 0x80000000
#define INT_MAX 0x7fffffff
#define UINT_MAX 4294967295U
#define INT_MIN (-INT_MAX - 1)
#define INT_MAX 2147483647
#define USHRT_MAX 0xffff
#define SHRT_MIN 0x8000
#define SHRT_MAX 0x7fff
#define USHRT_MAX 65535
#define SHRT_MIN (-32768)
#define SHRT_MAX 32767
#define UCHAR_MAX 0xff
#define UCHAR_MAX 255
#define CHAR_BIT 8

View File

@ -11,8 +11,13 @@ extern "C" {
#define NULL ((void *)0)
#endif
#ifdef __LP64__
typedef unsigned long size_t;
typedef long ptrdiff_t;
#else
typedef unsigned int size_t;
typedef int ptrdiff_t;
#endif
#define offsetof(type, member) __builtin_offsetof(type, member)

View File

@ -5,8 +5,13 @@
extern "C" {
#endif
#ifdef __LP64__
typedef long intptr_t;
typedef unsigned long uintptr_t;
#else
typedef int intptr_t;
typedef unsigned int uintptr_t;
#endif
typedef unsigned long long uint64_t;
typedef unsigned int uint32_t;

View File

@ -10,11 +10,11 @@ extern "C" {
int putchar(int c);
int puts(const char *s);
int snprintf(char *buf, size_t size, const char *fmt, ...);
int scnprintf(char *buf, size_t size, const char *fmt, ...);
int sprintf(char *buf, const char *fmt, ...);
int snprintf(char *buf, size_t size, const char *fmt, ...) __attribute__((format(printf, 3, 4)));
int scnprintf(char *buf, size_t size, const char *fmt, ...) __attribute__((format(printf, 3, 4)));
int sprintf(char *buf, const char *fmt, ...) __attribute__((format(printf, 2, 3)));
int printf(const char *fmt, ...);
int printf(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
/* Not sure this belongs here... */
typedef long long loff_t;
@ -53,7 +53,7 @@ extern FILE *stdin;
extern FILE *stdout;
extern FILE *stderr;
int fprintf(FILE *stream, const char *format, ...);
int fprintf(FILE *stream, const char *format, ...) __attribute__((format(printf, 2, 3)));
int fflush(FILE *stream);
FILE *fopen(const char *path, const char *mode);

View File

@ -75,10 +75,7 @@ int readchar_nonblock(void)
int puts(const char *s)
{
while(*s) {
putchar(*s);
s++;
}
putsnonl(s);
putchar('\n');
return 1;
}

View File

@ -76,9 +76,9 @@ static void gdb_stub(unsigned long pc, unsigned long sr,
case 'g': {
snprintf(buf, sizeof(buf),
"%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x"
"%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x"
"%08x%08x%08x",
"%08x%08lx%08lx%08lx%08lx%08lx%08lx%08lx%08lx%08lx%08lx%08lx%08lx%08lx%08lx%08lx"
"%08lx%08lx%08lx%08lx%08lx%08lx%08lx%08lx%08lx%08lx%08lx%08lx%08lx%08lx%08lx%08lx"
"%08lx%08lx%08lx",
0, r1, regs[2], regs[3], regs[4], regs[5], regs[6], regs[7],
regs[8], regs[9], regs[10], regs[11], regs[12], regs[13], regs[14], regs[15],
regs[16], regs[17], regs[18], regs[19], regs[20], regs[21], regs[22], regs[23],
@ -120,7 +120,7 @@ static void gdb_stub(unsigned long pc, unsigned long sr,
snprintf(buf, sizeof(buf), "E01");
break;
}
snprintf(buf, sizeof(buf), "%08x", value);
snprintf(buf, sizeof(buf), "%08lx", value);
break;
}
@ -156,7 +156,6 @@ static void gdb_stub(unsigned long pc, unsigned long sr,
}
default:
snprintf(buf, sizeof(buf), "");
break;
}

View File

@ -53,7 +53,7 @@ int memtest_access(unsigned int *addr)
array[0] = ZEROONE;
array[1] = array[0];
if (ctrl_bus_errors_read() - bus_errors) {
printf("memtest_access error @ 0x%0x, exiting memtest.\n", addr);
printf("memtest_access error @ %p, exiting memtest.\n", addr);
return 1;
}
@ -83,7 +83,7 @@ int memtest_bus(unsigned int *addr, unsigned long size)
if(rdata != ONEZERO) {
errors++;
#ifdef MEMTEST_BUS_DEBUG
printf("memtest_bus error @ 0x%0x: 0x%08x vs 0x%08x\n", addr + i, rdata, ONEZERO);
printf("memtest_bus error @ %p: 0x%08x vs 0x%08x\n", addr + i, rdata, ONEZERO);
#endif
}
}
@ -103,7 +103,7 @@ int memtest_bus(unsigned int *addr, unsigned long size)
if(rdata != ZEROONE) {
errors++;
#ifdef MEMTEST_BUS_DEBUG
printf("memtest_bus error @ 0x%0x:: 0x%08x vs 0x%08x\n", addr + i, rdata, ZEROONE);
printf("memtest_bus error @ %p:: 0x%08x vs 0x%08x\n", addr + i, rdata, ZEROONE);
#endif
}
}
@ -139,7 +139,7 @@ int memtest_addr(unsigned int *addr, unsigned long size, int random)
if(rdata != i) {
errors++;
#ifdef MEMTEST_ADDR_DEBUG
printf("memtest_addr error @ 0x%0x: 0x%08x vs 0x%08x\n", addr + i, rdata, i);
printf("memtest_addr error @ %p: 0x%08x vs 0x%08x\n", addr + i, rdata, i);
#endif
}
}
@ -202,7 +202,7 @@ int memtest_data(unsigned int *addr, unsigned long size, int random)
if(rdata != seed_32) {
errors++;
#ifdef MEMTEST_DATA_DEBUG
printf("memtest_data error @%0x: 0x%08x vs 0x%08x\n", addr + i, rdata, seed_32);
printf("memtest_data error @ %p: 0x%08x vs 0x%08x\n", addr + i, rdata, seed_32);
#endif
}
if (i%0x8000 == 0)
@ -224,7 +224,7 @@ void memspeed(unsigned int *addr, unsigned long size, bool read_only)
__attribute__((unused)) unsigned long data;
const unsigned int sz = sizeof(unsigned long);
printf("Memspeed at 0x%p (", addr);
printf("Memspeed at %p (", addr);
print_size(size);
printf(")...\n");
@ -279,7 +279,7 @@ int memtest(unsigned int *addr, unsigned long maxsize)
unsigned long addr_size = MEMTEST_ADDR_SIZE < maxsize ? MEMTEST_ADDR_SIZE : maxsize;
unsigned long data_size = maxsize;
printf("Memtest at 0x%p (", addr);
printf("Memtest at %p (", addr);
print_size(data_size);
printf(")...\n");

View File

@ -61,6 +61,4 @@ void init_progression_bar(int max)
spin = 0;
if (progress_max && progress_max != FILESIZE_MAX)
printf("[%*s]\r[", HASHES_PER_LINE, "");
else
printf("");
}

View File

@ -186,7 +186,7 @@ int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
case 'p':
if (field_width == -1) {
field_width = 2*sizeof(void *);
flags |= PRINTF_ZEROPAD;
flags |= PRINTF_ZEROPAD | PRINTF_SPECIAL;
}
str = number(str, end,
(unsigned long) va_arg(args, void *),

View File

@ -23,7 +23,7 @@ uint32_t rd_errors;
__attribute__((unused)) static void cdelay(int i)
{
#ifndef CONFIG_SIM_DISABLE_DELAYS
#ifndef CONFIG_DISABLE_DELAYS
while(i > 0) {
__asm__ volatile(CONFIG_CPU_NOP);
i--;
@ -130,7 +130,7 @@ void sdram_bist_loop(uint32_t loop, uint32_t burst_length, uint32_t random) {
static uint32_t compute_speed_mibs(uint32_t length, uint32_t ticks) {
uint32_t speed;
//printf("(%lu, %lu)", length, ticks);
//printf("(%u, %u)", length, ticks);
speed = length*(CONFIG_CLOCK_FREQUENCY/(1024*1024))/ticks;
return speed;
}

View File

@ -37,7 +37,7 @@
__attribute__((unused)) static void cdelay(int i)
{
#ifndef CONFIG_SIM_DISABLE_DELAYS
#ifndef CONFIG_DISABLE_DELAYS
while(i > 0) {
__asm__ volatile(CONFIG_CPU_NOP);
i--;
@ -102,22 +102,24 @@ static unsigned char sdram_dfii_get_wrphase(void) {
}
static void sdram_dfii_pix_address_write(unsigned char phase, unsigned int value) {
#if (SDRAM_PHY_PHASES > 8)
#error "More than 8 DFI phases not supported"
#endif
switch (phase) {
#if (SDRAM_PHY_PHASES > 4)
case 7: sdram_dfii_pi7_address_write(value); break;
case 6: sdram_dfii_pi6_address_write(value); break;
case 5: sdram_dfii_pi5_address_write(value); break;
case 4: sdram_dfii_pi4_address_write(value); break;
#endif
#if (SDRAM_PHY_PHASES > 2)
case 3:
sdram_dfii_pi3_address_write(value);
break;
case 2:
sdram_dfii_pi2_address_write(value);
break;
case 3: sdram_dfii_pi3_address_write(value); break;
case 2: sdram_dfii_pi2_address_write(value); break;
#endif
#if (SDRAM_PHY_PHASES > 1)
case 1:
sdram_dfii_pi1_address_write(value);
break;
case 1: sdram_dfii_pi1_address_write(value); break;
#endif
default:
sdram_dfii_pi0_address_write(value);
default: sdram_dfii_pi0_address_write(value);
}
}
@ -132,22 +134,24 @@ static void sdram_dfii_piwr_address_write(unsigned int value) {
}
static void sdram_dfii_pix_baddress_write(unsigned char phase, unsigned int value) {
#if (SDRAM_PHY_PHASES > 8)
#error "More than 8 DFI phases not supported"
#endif
switch (phase) {
#if (SDRAM_PHY_PHASES > 4)
case 7: sdram_dfii_pi7_baddress_write(value); break;
case 6: sdram_dfii_pi6_baddress_write(value); break;
case 5: sdram_dfii_pi5_baddress_write(value); break;
case 4: sdram_dfii_pi4_baddress_write(value); break;
#endif
#if (SDRAM_PHY_PHASES > 2)
case 3:
sdram_dfii_pi3_baddress_write(value);
break;
case 2:
sdram_dfii_pi2_baddress_write(value);
break;
case 3: sdram_dfii_pi3_baddress_write(value); break;
case 2: sdram_dfii_pi2_baddress_write(value); break;
#endif
#if (SDRAM_PHY_PHASES > 1)
case 1:
sdram_dfii_pi1_baddress_write(value);
break;
case 1: sdram_dfii_pi1_baddress_write(value); break;
#endif
default:
sdram_dfii_pi0_baddress_write(value);
default: sdram_dfii_pi0_baddress_write(value);
}
}
@ -162,22 +166,24 @@ static void sdram_dfii_piwr_baddress_write(unsigned int value) {
}
static void command_px(unsigned char phase, unsigned int value) {
#if (SDRAM_PHY_PHASES > 8)
#error "More than 8 DFI phases not supported"
#endif
switch (phase) {
#if (SDRAM_PHY_PHASES > 4)
case 7: command_p7(value); break;
case 6: command_p6(value); break;
case 5: command_p5(value); break;
case 4: command_p4(value); break;
#endif
#if (SDRAM_PHY_PHASES > 2)
case 3:
command_p3(value);
break;
case 2:
command_p2(value);
break;
case 3: command_p3(value); break;
case 2: command_p2(value); break;
#endif
#if (SDRAM_PHY_PHASES > 1)
case 1:
command_p1(value);
break;
case 1: command_p1(value); break;
#endif
default:
command_p0(value);
default: command_p0(value);
}
}
@ -255,15 +261,19 @@ int _sdram_write_leveling_cmd_scan = 1;
int _sdram_write_leveling_cmd_delay = 0;
int _sdram_write_leveling_dat_delays[16];
int _sdram_write_leveling_cdly_range_start = -1;
int _sdram_write_leveling_cdly_range_end = -1;
static void sdram_write_leveling_on(void)
{
sdram_dfii_pi0_address_write(DDRX_MR1 | (1 << 7));
sdram_dfii_pi0_baddress_write(1);
// Flip write leveling bit in the Mode Register, as it is disabled by default
sdram_dfii_pi0_address_write(DDRX_MR_WRLVL_RESET ^ (1 << DDRX_MR_WRLVL_BIT));
sdram_dfii_pi0_baddress_write(DDRX_MR_WRLVL_ADDRESS);
command_p0(DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS);
#ifdef SDRAM_PHY_DDR4_RDIMM
sdram_dfii_pi0_address_write((DDRX_MR1 | (1 << 7)) ^ 0x2BF8) ;
sdram_dfii_pi0_baddress_write(1 ^ 0xF);
sdram_dfii_pi0_address_write((DDRX_MR_WRLVL_RESET ^ (1 << DDRX_MR_WRLVL_BIT)) ^ 0x2BF8) ;
sdram_dfii_pi0_baddress_write(DDRX_MR_WRLVL_ADDRESS ^ 0xF);
command_p0(DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS);
#endif
@ -272,13 +282,13 @@ static void sdram_write_leveling_on(void)
static void sdram_write_leveling_off(void)
{
sdram_dfii_pi0_address_write(DDRX_MR1);
sdram_dfii_pi0_baddress_write(1);
sdram_dfii_pi0_address_write(DDRX_MR_WRLVL_RESET);
sdram_dfii_pi0_baddress_write(DDRX_MR_WRLVL_ADDRESS);
command_p0(DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS);
#ifdef SDRAM_PHY_DDR4_RDIMM
sdram_dfii_pi0_address_write(DDRX_MR1 ^ 0x2BF8);
sdram_dfii_pi0_baddress_write(1 ^ 0xF);
sdram_dfii_pi0_address_write(DDRX_MR_WRLVL_RESET ^ 0x2BF8);
sdram_dfii_pi0_baddress_write(DDRX_MR_WRLVL_ADDRESS ^ 0xF);
command_p0(DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS);
#endif
@ -345,7 +355,7 @@ static void sdram_write_leveling_rst_delay(int module) {
for(i=0; i<ddrphy_half_sys8x_taps_read(); i++) {
ddrphy_wdly_dqs_inc_write(1);
cdelay(100);
}
}
#endif
/* Un-select module */
@ -545,12 +555,21 @@ int sdram_write_leveling(void)
int cdly_range_end;
int cdly_range_step;
printf(" tCK/4 taps: %d\n", ddrphy_half_sys8x_taps_read());
if (_sdram_write_leveling_cmd_scan) {
/* Center write leveling by varying cdly. Searching through all possible
* values is slow, but we can use a simple optimization method of iterativly
* scanning smaller ranges with decreasing step */
cdly_range_start = 0;
cdly_range_end = 2*ddrphy_half_sys8x_taps_read(); /* Limit Clk/Cmd scan to 1/2 tCK */
if (_sdram_write_leveling_cdly_range_start != -1)
cdly_range_start = _sdram_write_leveling_cdly_range_start;
else
cdly_range_start = 0;
if (_sdram_write_leveling_cdly_range_end != -1)
cdly_range_end = _sdram_write_leveling_cdly_range_end;
else
cdly_range_end = 2*ddrphy_half_sys8x_taps_read(); /* Limit Clk/Cmd scan to 1/2 tCK */
printf(" Cmd/Clk scan (%d-%d)\n", cdly_range_start, cdly_range_end);
if (SDRAM_PHY_DELAYS > 32)
cdly_range_step = SDRAM_PHY_DELAYS/8;
@ -887,7 +906,7 @@ static void sdram_write_latency_calibration(void) {
for(module=0; module<SDRAM_PHY_MODULES; module++) {
/* Scan possible write windows */
best_score = 0;
best_bitslip = 0;
best_bitslip = -1;
for(bitslip=0; bitslip<SDRAM_PHY_BITSLIPS; bitslip+=2) { /* +2 for tCK steps */
score = 0;
/* Select module */
@ -917,7 +936,10 @@ static void sdram_write_latency_calibration(void) {
bitslip = best_bitslip;
else
bitslip = _sdram_write_leveling_bitslips[module];
printf("m%d:%d ", module, bitslip);
if (bitslip == -1)
printf("m%d:- ", module);
else
printf("m%d:%d ", module, bitslip);
/* Select best write window */
ddrphy_dly_sel_write(1 << module);
@ -998,7 +1020,7 @@ int sdram_init(void)
_sdram_write_leveling_cmd_scan = 0;
_sdram_write_leveling_cmd_delay = SDRAM_PHY_CMD_DELAY;
#endif
printf("Initializing SDRAM @0x%08x...\n", MAIN_RAM_BASE);
printf("Initializing SDRAM @0x%08lx...\n", MAIN_RAM_BASE);
sdram_software_control_on();
#if CSR_DDRPHY_RST_ADDR
ddrphy_rst_write(1);

View File

@ -51,7 +51,7 @@ void sata_read(uint32_t sector, uint32_t count, uint8_t* buf)
for (i=0; i<count; i++) {
uint8_t done = 0;
while (done == 0) {
sata_sector2mem_base_write((uint64_t) buf);
sata_sector2mem_base_write((uint64_t)(uintptr_t) buf);
sata_sector2mem_sector_write(sector + i);
sata_sector2mem_start_write(1);
while ((sata_sector2mem_done_read() & 0x1) == 0);
@ -80,7 +80,7 @@ void sata_write(uint32_t sector, uint32_t count, uint8_t* buf)
for (i=0; i<count; i++) {
uint8_t done = 0;
while (done == 0) {
sata_mem2sector_base_write((uint64_t) buf);
sata_mem2sector_base_write((uint64_t)(uintptr_t) buf);
sata_mem2sector_sector_write(sector + i);
sata_mem2sector_start_write(1);
while ((sata_sector2mem_done_read() & 0x1) == 0);

View File

@ -106,6 +106,7 @@ void sdcard_set_clk_freq(uint32_t clk_freq, int show) {
uint32_t divider;
divider = clk_freq ? CONFIG_CLOCK_FREQUENCY/clk_freq : 256;
divider = pow2_round_up(divider);
divider <<= 1; /* NOTE: workaround for occasional sdcardboot failure */
divider = min(max(divider, 2), 256);
#ifdef SDCARD_DEBUG
show = 1;
@ -473,7 +474,7 @@ void sdcard_read(uint32_t block, uint32_t count, uint8_t* buf)
{
/* Initialize DMA Writer */
sdblock2mem_dma_enable_write(0);
sdblock2mem_dma_base_write((uint64_t) buf);
sdblock2mem_dma_base_write((uint64_t)(uintptr_t) buf);
sdblock2mem_dma_length_write(512*count);
sdblock2mem_dma_enable_write(1);
@ -504,7 +505,7 @@ void sdcard_write(uint32_t block, uint32_t count, uint8_t* buf)
while (count--) {
/* Initialize DMA Reader */
sdmem2block_dma_enable_write(0);
sdmem2block_dma_base_write((uint64_t) buf);
sdmem2block_dma_base_write((uint64_t)(uintptr_t) buf);
sdmem2block_dma_length_write(512);
sdmem2block_dma_enable_write(1);

View File

@ -111,13 +111,31 @@ def dump_registers(port):
wb.close()
def read_memory(port, addr):
wb = RemoteClient(port=port)
wb.open()
print("0x{:08x}".format(wb.read(addr)))
wb.close()
def write_memory(port, addr, data):
wb = RemoteClient(port=port)
wb.open()
wb.write(addr, data)
wb.close()
# Run ----------------------------------------------------------------------------------------------
def main():
parser = argparse.ArgumentParser(description="LiteX Client utility")
parser.add_argument("--port", default="1234", help="Host bind port")
parser.add_argument("--ident", action="store_true", help="Dump FPGA identifier")
parser.add_argument("--regs", action="store_true", help="Dump FPGA registers")
parser.add_argument("--port", default="1234", help="Host bind port")
parser.add_argument("--ident", action="store_true", help="Dump SoC identifier")
parser.add_argument("--regs", action="store_true", help="Dump SoC registers")
parser.add_argument("--read", default=None, help="Do a MMAP Read to SoC bus (--read addr)")
parser.add_argument("--write", default=None, nargs=2, help="Do a MMAP Write to SoC bus (--write addr data)")
args = parser.parse_args()
port = int(args.port, 0)
@ -128,5 +146,11 @@ def main():
if args.regs:
dump_registers(port=port)
if args.read:
read_memory(port=port, addr=int(args.read, 0))
if args.write:
write_memory(port=port, addr=int(args.write[0], 0), data=int(args.write[1], 0))
if __name__ == "__main__":
main()

View File

@ -67,7 +67,7 @@ def generate_dts(d, initrd_start=None, initrd_size=None, polling=False):
#address-cells = <1>;
#size-cells = <0>;
timebase-frequency = <{sys_clk_freq}>;
""".format(sys_clk_freq=int(50e6) if "sim" in d["constants"] else d["constants"]["config_clock_frequency"])
""".format(sys_clk_freq=d["constants"]["config_clock_frequency"])
cpus = range(int(d["constants"]["config_cpu_count"]))
for cpu in cpus:
dts += """
@ -77,6 +77,7 @@ def generate_dts(d, initrd_start=None, initrd_size=None, polling=False):
riscv,isa = "rv32ima";
mmu-type = "riscv,sv32";
reg = <{cpu}>;
clock-frequency = <{sys_clk_freq}>;
status = "okay";
L{irq}: interrupt-controller {{
#interrupt-cells = <0x00000001>;
@ -84,7 +85,7 @@ def generate_dts(d, initrd_start=None, initrd_size=None, polling=False):
compatible = "riscv,cpu-intc";
}};
}};
""".format(cpu=cpu, irq=cpu)
""".format(cpu=cpu, irq=cpu, sys_clk_freq=d["constants"]["config_clock_frequency"])
dts += """
};
"""
@ -98,7 +99,7 @@ def generate_dts(d, initrd_start=None, initrd_size=None, polling=False):
cpu@0 {{
compatible = "opencores,or1200-rtlsvn481";
reg = <0>;
clock-frequency = <{sys_clk_freq}>;
clock-frequency = <{sys_clk_freq}>;
}};
}};
""".format(sys_clk_freq=d["constants"]["config_clock_frequency"])
@ -203,6 +204,7 @@ def generate_dts(d, initrd_start=None, initrd_size=None, polling=False):
tx-fifo-depth = <{ethmac_tx_slots}>;
rx-fifo-depth = <{ethmac_rx_slots}>;
{ethmac_interrupt}
status = "okay";
}};
""".format(
ethphy_csr_base = d["csr_bases"]["ethphy"],
@ -272,7 +274,7 @@ def generate_dts(d, initrd_start=None, initrd_size=None, polling=False):
status = "okay";
}};
""".format(
mmc_csr_base = d["csr_bases"]["sdcore"],
mmc_csr_base = d["csr_bases"]["sdphy"],
sdphy_csr_base = d["csr_bases"]["sdphy"],
sdcore_csr_base = d["csr_bases"]["sdcore"],
sdblock2mem = d["csr_bases"]["sdblock2mem"],

View File

@ -3,13 +3,14 @@
#
# This file is part of LiteX.
#
# Copyright (c) 2015-2019 Florent Kermarrec <florent@enjoy-digital.fr>
# Copyright (c) 2015-2021 Florent Kermarrec <florent@enjoy-digital.fr>
# Copyright (c) 2019 Sean Cross <sean@xobs.io>
# Copyright (c) 2018 Felix Held <felix-github@felixheld.de>
# SPDX-License-Identifier: BSD-2-Clause
import argparse
import os
import sys
import socket
import time
@ -174,6 +175,10 @@ def main():
parser.add_argument("--uart-port", default=None, help="Set UART port")
parser.add_argument("--uart-baudrate", default=115200, help="Set UART baudrate")
# JTAG arguments
parser.add_argument("--jtag", action="store_true", help="Select JTAG interface")
parser.add_argument("--jtag-config", default="openocd_xc7_ft232.cfg", help="OpenOCD JTAG configuration file")
# UDP arguments
parser.add_argument("--udp", action="store_true", help="Select UDP interface")
parser.add_argument("--udp-ip", default="192.168.1.50", help="Set UDP remote IP address")
@ -203,6 +208,15 @@ def main():
print("[CommUART] port: {} / baudrate: {} / ".format(uart_port, uart_baudrate), end="")
comm = CommUART(uart_port, uart_baudrate, debug=args.debug)
# JTAG mode
elif args.jtag:
from litex.tools.litex_term import JTAGUART
from litex.tools.remote.comm_uart import CommUART
bridge = JTAGUART(config=args.jtag_config)
bridge.open()
print("[CommUART] port: JTAG / ", end="")
comm = CommUART(os.ttyname(bridge.name), debug=args.debug)
# UDP mode
elif args.udp:
from litex.tools.remote.comm_udp import CommUDP

View File

@ -8,6 +8,7 @@
# Copyright (c) 2017 Pierre-Olivier Vauboin <po@lambdaconcept>
# SPDX-License-Identifier: BSD-2-Clause
import sys
import argparse
from migen import *
@ -114,7 +115,7 @@ def get_sdram_phy_settings(memtype, data_width, clk_freq):
elif memtype in ["DDR2", "DDR3"]:
# Settings from s7ddrphy
tck = 2/(2*nphases*clk_freq)
cl, cwl = get_cl_cw(memtype, tck)
cl, cwl = get_default_cl_cwl(memtype, tck)
cl_sys_latency = get_sys_latency(nphases, cl)
cwl_sys_latency = get_sys_latency(nphases, cwl)
rdphase = get_sys_phase(nphases, cl_sys_latency, cl)
@ -124,7 +125,7 @@ def get_sdram_phy_settings(memtype, data_width, clk_freq):
elif memtype == "DDR4":
# Settings from usddrphy
tck = 2/(2*nphases*clk_freq)
cl, cwl = get_cl_cw(memtype, tck)
cl, cwl = get_default_cl_cwl(memtype, tck)
cl_sys_latency = get_sys_latency(nphases, cl)
cwl_sys_latency = get_sys_latency(nphases, cwl)
rdphase = get_sys_phase(nphases, cl_sys_latency, cl)
@ -326,6 +327,42 @@ class SimSoC(SoCCore):
# Build --------------------------------------------------------------------------------------------
def generate_gtkw_savefile(builder, vns, trace_fst):
from litex.build.sim import gtkwave as gtkw
dumpfile = os.path.join(builder.gateware_dir, "sim.{}".format("fst" if trace_fst else "vcd"))
savefile = os.path.join(builder.gateware_dir, "sim.gtkw")
soc = builder.soc
with gtkw.GTKWSave(vns, savefile=savefile, dumpfile=dumpfile) as save:
save.clocks()
save.fsm_states(soc)
save.add(soc.bus.slaves["main_ram"], mappers=[gtkw.wishbone_sorter(), gtkw.wishbone_colorer()])
if hasattr(soc, 'sdrphy'):
# all dfi signals
save.add(soc.sdrphy.dfi, mappers=[gtkw.dfi_sorter(), gtkw.dfi_in_phase_colorer()])
# each phase in separate group
with save.gtkw.group("dfi phaseX", closed=True):
for i, phase in enumerate(soc.sdrphy.dfi.phases):
save.add(phase, group_name="dfi p{}".format(i), mappers=[
gtkw.dfi_sorter(phases=False),
gtkw.dfi_in_phase_colorer(),
])
# only dfi command/data signals
def dfi_group(name, suffixes):
save.add(soc.sdrphy.dfi, group_name=name, mappers=[
gtkw.regex_filter(gtkw.suffixes2re(suffixes)),
gtkw.dfi_sorter(),
gtkw.dfi_per_phase_colorer(),
])
dfi_group("dfi commands", ["cas_n", "ras_n", "we_n"])
dfi_group("dfi commands", ["wrdata"])
dfi_group("dfi commands", ["wrdata_mask"])
dfi_group("dfi commands", ["rddata"])
def sim_args(parser):
builder_args(parser)
soc_sdram_args(parser)
@ -351,6 +388,7 @@ def sim_args(parser):
parser.add_argument("--trace-end", default="-1", help="Time to end tracing (ps)")
parser.add_argument("--opt-level", default="O3", help="Compilation optimization level")
parser.add_argument("--sim-debug", action="store_true", help="Add simulation debugging modules")
parser.add_argument("--gtkwave-savefile", action="store_true", help="Generate GTKWave savefile")
def main():
parser = argparse.ArgumentParser(description="Generic LiteX SoC Simulation")
@ -433,6 +471,8 @@ def main():
)
if args.with_analyzer:
soc.analyzer.export_csv(vns, "analyzer.csv")
if args.gtkwave_savefile:
generate_gtkw_savefile(builder, vns, args.trace_fst)
if __name__ == "__main__":
main()

View File

@ -17,24 +17,47 @@ import threading
import multiprocessing
import argparse
import json
import pty
import telnetlib
import socket
# Console ------------------------------------------------------------------------------------------
if sys.platform == "win32":
import ctypes
import msvcrt
class Console:
def configure(self):
pass
# https://stackoverflow.com/a/36760881
# ENABLE_VIRTUAL_TERMINAL_PROCESSING
kernel32 = ctypes.windll.kernel32
kernel32.SetConsoleMode(kernel32.GetStdHandle(-11), 7)
def unconfigure(self):
pass
def getkey(self):
return msvcrt.getch()
# getch doesn't return Virtual Keycodes, but rather
# PS/2 Scan Codes. Keycodes starting with 0xE0 are
# worth handling.
def escape_char(self, b):
return b == b"\xe0"
def handle_escape(self, b):
return {
b"H" : b"\x1b[A", # Up
b"P" : b"\x1b[B", # Down
b"K" : b"\x1b[D", # Left
b"M" : b"\x1b[C", # Right
b"G" : b"\x1b[H", # Home
b"O" : b"\x1b[F", # End
b"R" : b"\x1b[2~", # Insert
b"S" : b"\x1b[3~", # Delete
}.get(b, None) # TODO: Handle ESC? Others?
else:
import termios
import pty
class Console:
def __init__(self):
self.fd = sys.stdin.fileno()
@ -53,6 +76,12 @@ else:
def getkey(self):
return os.read(self.fd, 1)
def escape_char(self, b):
return False
def handle_escape(self, b):
return None
# Crossover UART ----------------------------------------------------------------------------------
from litex import RemoteClient
@ -97,43 +126,68 @@ class CrossoverUART:
from litex.build.openocd import OpenOCD
class JTAGUART:
def __init__(self, config="openocd_xc7_ft2232.cfg", port=20000): # FIXME: add command line arguments
def __init__(self, config="openocd_xc7_ft2232.cfg", port=20000):
self.config = config
self.port = port
def open(self):
self.file, self.name = pty.openpty()
self.jtag2telnet_thread = multiprocessing.Process(target=self.jtag2telnet)
self.jtag2telnet_thread.start()
self.jtag2tcp_thread = multiprocessing.Process(target=self.jtag2tcp)
self.jtag2tcp_thread.start()
time.sleep(0.5)
self.pty2telnet_thread = multiprocessing.Process(target=self.pty2telnet)
self.telnet2pty_thread = multiprocessing.Process(target=self.telnet2pty)
self.telnet = telnetlib.Telnet("localhost", self.port)
self.pty2telnet_thread.start()
self.telnet2pty_thread.start()
self.pty2tcp_thread = multiprocessing.Process(target=self.pty2tcp)
self.tcp2pty_thread = multiprocessing.Process(target=self.tcp2pty)
self.tcp = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.tcp.connect(("localhost", self.port))
self.pty2tcp_thread.start()
self.tcp2pty_thread.start()
def close(self):
self.jtag2telnet_thread.terminate()
self.pty2telnet_thread.terminate()
self.telnet2pty_thread.terminate()
self.jtag2tcp_thread.terminate()
self.pty2tcp_thread.terminate()
self.tcp2pty_thread.terminate()
def jtag2telnet(self):
def jtag2tcp(self):
prog = OpenOCD(self.config)
prog.stream(self.port)
def pty2telnet(self):
def pty2tcp(self):
while True:
r = os.read(self.file, 1)
self.telnet.write(r)
if r == bytes("\n".encode("utf-8")):
self.telnet.write("\r".encode("utf-8"))
self.telnet.write("\n".encode("utf-8"))
self.tcp.send(r)
def telnet2pty(self):
def tcp2pty(self):
while True:
r = self.telnet.read_some()
r = self.tcp.recv(1)
os.write(self.file, bytes(r))
# Intel/Altera JTAG UART via nios2-terminal
class Nios2Terminal():
def __init__(self):
from subprocess import Popen, PIPE
p = Popen("nios2-terminal", stdin=PIPE, stdout=PIPE)
self.p = p
def read(self):
return self.p.stdout.read(1)
def in_waiting(self):
# unfortunately p.stdout does not provide
# information about awaiting input
return False
def write(self, data):
if data is not None:
self.p.stdin.write(data)
try:
self.p.stdin.flush()
except BrokenPipeError:
print("nios2-terminal has terminated, exiting...\n")
sys.exit(1)
def close(self):
self.p.terminate()
# SFL ----------------------------------------------------------------------------------------------
sfl_prompt_req = b"F7: boot from serial\n"
@ -149,8 +203,6 @@ sfl_outstanding = 128
sfl_cmd_abort = b"\x00"
sfl_cmd_load = b"\x01"
sfl_cmd_jump = b"\x02"
sfl_cmd_flash = b"\x04"
sfl_cmd_reboot = b"\x05"
# Replies
sfl_ack_success = b"K"
@ -221,7 +273,7 @@ def crc16(l):
# LiteXTerm ----------------------------------------------------------------------------------------
class LiteXTerm:
def __init__(self, serial_boot, kernel_image, kernel_address, json_images, flash):
def __init__(self, serial_boot, kernel_image, kernel_address, json_images):
self.serial_boot = serial_boot
assert not (kernel_image is not None and json_images is not None)
self.mem_regions = {}
@ -235,7 +287,6 @@ class LiteXTerm:
self.mem_regions[os.path.join(json_dir, k)] = v
self.boot_address = self.mem_regions[list(self.mem_regions.keys())[-1]]
f.close()
self.flash = flash
self.reader_alive = False
self.writer_alive = False
@ -296,7 +347,7 @@ class LiteXTerm:
def receive_upload_response(self):
reply = self.port.read()
if reply == sfl_ack_success:
return
return True
elif reply == sfl_ack_crcerror:
print("[LXTERM] Upload to device failed due to data corruption (CRC error)")
else:
@ -309,8 +360,7 @@ class LiteXTerm:
length = f.tell()
f.seek(0, 0)
action = "Flashing" if self.flash else "Uploading"
print(f"[LXTERM] {action} {filename} to 0x{address:08x} ({length} bytes)...")
print(f"[LXTERM] Uploading {filename} to 0x{address:08x} ({length} bytes)...")
# Prepare parameters
current_address = address
@ -329,12 +379,9 @@ class LiteXTerm:
# Send frame if max outstanding not reached.
if outstanding <= sfl_outstanding:
# Prepare frame.
frame = SFLFrame()
frame = SFLFrame()
frame.cmd = sfl_cmd_load
frame_data = f.read(min(remaining, self.payload_length-4))
if self.flash:
frame.cmd = sfl_cmd_flash
else:
frame.cmd = sfl_cmd_load
frame.payload = current_address.to_bytes(4, "big")
frame.payload += frame_data
@ -350,10 +397,12 @@ class LiteXTerm:
# Inter-frame delay.
time.sleep(self.delay)
# Read response if availables.
# Read response if available.
while self.port.in_waiting:
self.receive_upload_response()
outstanding -= 1
ack = self.receive_upload_response()
if ack:
outstanding -= 1
break
# Get remaining responses.
for _ in range(outstanding):
@ -373,12 +422,6 @@ class LiteXTerm:
frame.payload = int(self.boot_address, 16).to_bytes(4, "big")
self.send_frame(frame)
def reboot(self):
print("[LXTERM] Rebooting the device.")
frame = SFLFrame()
frame.cmd = sfl_cmd_reboot
self.send_frame(frame)
def detect_prompt(self, data):
if len(data):
self.prompt_detect_buffer = self.prompt_detect_buffer[1:] + data
@ -403,12 +446,8 @@ class LiteXTerm:
self.port.write(sfl_magic_ack)
for filename, base in self.mem_regions.items():
self.upload(filename, int(base, 16))
if self.flash:
# clear mem_regions to avoid re-flashing on next reboot(s)
self.mem_regions = {}
else:
self.boot()
print("[LXTERM] Done.");
self.boot()
print("[LXTERM] Done.")
def reader(self):
try:
@ -445,6 +484,10 @@ class LiteXTerm:
self.stop()
elif b == b"\n":
self.port.write(b"\x0a")
elif self.console.escape_char(b):
b = self.console.getkey()
ansi_seq = self.console.handle_escape(b)
self.port.write(ansi_seq)
else:
self.port.write(b)
except:
@ -479,25 +522,31 @@ class LiteXTerm:
def _get_args():
parser = argparse.ArgumentParser()
parser.add_argument("port", help="Serial port")
parser.add_argument("--speed", default=115200, help="Aerial baudrate")
parser.add_argument("port", help="Serial port (eg /dev/tty*, crossover, jtag_uart, jtag_atlantic)")
parser.add_argument("--speed", default=115200, help="Serial baudrate")
parser.add_argument("--serial-boot", default=False, action='store_true', help="Automatically initiate serial boot")
parser.add_argument("--kernel", default=None, help="Kernel image")
parser.add_argument("--kernel-adr", default="0x40000000", help="Kernel address (or flash offset with --flash)")
parser.add_argument("--kernel-adr", default="0x40000000", help="Kernel address")
parser.add_argument("--images", default=None, help="JSON description of the images to load to memory")
parser.add_argument("--no-crc", default=False, action='store_true', help="Disable CRC check (speedup serialboot)")
parser.add_argument("--flash", default=False, action='store_true', help="Flash data with serialboot command")
parser.add_argument("--jtag-config", default="openocd_xc7_ft2232.cfg", help="OpenOCD JTAG configuration file with jtag_uart")
return parser.parse_args()
def main():
args = _get_args()
if args.no_crc:
print("[LXTERM] --no-crc is deprecated and now does nothing (CRC checking is now fast)")
term = LiteXTerm(args.serial_boot, args.kernel, args.kernel_adr, args.images, args.flash)
term = LiteXTerm(args.serial_boot, args.kernel, args.kernel_adr, args.images)
bridge_cls = {"crossover": CrossoverUART, "jtag_uart": JTAGUART}.get(args.port, None)
if bridge_cls is not None:
bridge = bridge_cls()
if sys.platform == "win32":
if args.port in ["crossover", "jtag_uart"]:
raise NotImplementedError
bridge_cls = {"crossover": CrossoverUART, "jtag_uart": JTAGUART}.get(args.port, None)
bridge_kwargs = {"jtag_uart": {"config": args.jtag_config}}.get(args.port, {})
if args.port == "jtag_atlantic":
term.port = Nios2Terminal()
port = args.port
term.payload_length = 128
term.delay = 1e-6
elif bridge_cls is not None:
bridge = bridge_cls(**bridge_kwargs)
bridge.open()
port = os.ttyname(bridge.name)
else:

View File

@ -62,7 +62,7 @@ from litex.tools.remote.csr_builder import CSRBuilder
# CommUSB ------------------------------------------------------------------------------------------
class CommUSB(CSRBuilder):
def __init__(self, vid=None, pid=None, max_retries=10, csr_csr=None, debug=False):
def __init__(self, vid=None, pid=None, max_retries=10, csr_csv=None, debug=False):
CSRBuilder.__init__(self, comm=self, csr_csv=csr_csv)
self.vid = vid
self.pid = pid

View File

@ -151,6 +151,8 @@ if "update" in sys.argv[1:]:
os.chdir(os.path.join(current_path, name))
subprocess.check_call("git checkout master", shell=True)
subprocess.check_call("git pull --ff-only", shell=True)
if need_recursive:
subprocess.check_call("git submodule update --init --recursive", shell=True)
if sha1 is not None:
os.chdir(os.path.join(current_path, name))
os.system("git checkout {:7x}".format(sha1))

View File

@ -41,7 +41,6 @@ setup(
"litex_cli=litex.tools.litex_client:main",
"litex_sim=litex.tools.litex_sim:main",
"litex_read_verilog=litex.tools.litex_read_verilog:main",
"litex_simple=litex.boards.targets.simple:main",
"litex_json2dts=litex.tools.litex_json2dts:main",
"litex_bare_metal_demo=litex.soc.software.demo.demo:main",
# short names

63
test/test_timer.py Normal file
View File

@ -0,0 +1,63 @@
import unittest
from migen import *
from litex.soc.cores.timer import Timer
class TestTimer(unittest.TestCase):
def test_one_shot_software_polling(self):
def generator(timer):
clock_cycles = 25
yield from timer._en.write(0)
yield from timer._load.write(clock_cycles)
yield from timer._reload.write(0)
yield from timer._en.write(1)
yield from timer._update_value.write(1)
yield
self.assertTrue((yield timer._value.status) > 0)
while (yield timer._value.status) > 0:
yield from timer._update_value.write(1)
yield
self.assertEqual((yield timer._value.status), 0)
timer = Timer()
run_simulation(timer, generator(timer))
def test_periodic_timer_software_polling(self):
def generator(timer):
clock_cycles = 25
yield from timer._en.write(0)
yield from timer._load.write(0)
yield from timer._reload.write(clock_cycles)
yield from timer._en.write(1)
yield from timer._update_value.write(1)
yield
self.assertTrue((yield timer._value.status) > 0)
while (yield timer._value.status) > 0:
yield from timer._update_value.write(1)
yield
# Ensure that the timer reloads
self.assertEqual((yield timer._value.status), clock_cycles)
timer = Timer()
run_simulation(timer, generator(timer))
def test_one_shot_timer_interrupts(self):
def generator(timer):
clock_cycles = 25
yield from timer._en.write(0)
yield from timer._load.write(clock_cycles)
yield from timer._reload.write(0)
yield from timer.ev.enable.write(1)
self.assertEqual(1, (yield timer.ev.zero.trigger))
yield from timer._en.write(1)
while (yield timer.ev.zero.trigger != 0) and clock_cycles >= -5:
yield
clock_cycles -= 1
self.assertEqual(0, (yield timer.ev.zero.trigger))
timer = Timer()
run_simulation(timer, generator(timer))