This commit is contained in:
Sean Cross 2019-04-19 16:47:55 +08:00
commit c780fb22b7
29 changed files with 633 additions and 390 deletions

View file

@ -1,4 +1,4 @@
Unless otherwise noted, LiteX is copyright (C) 2012-2018 Florent Kermarrec.
Unless otherwise noted, LiteX is copyright (C) 2012-2019 Florent Kermarrec.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,

2
README
View file

@ -5,7 +5,7 @@
Migen inside
Build your hardware, easily!
Copyright 2012-2018 / EnjoyDigital
Copyright 2012-2019 / EnjoyDigital
[> Intro
--------

View file

@ -14,6 +14,9 @@ from litex.soc.integration.builder import *
from litedram.modules import EDY4016A
from litedram.phy import usddrphy
from liteeth.phy.ku_1000basex import KU_1000BASEX
from liteeth.core.mac import LiteEthMAC
# CRG ----------------------------------------------------------------------------------------------
class _CRG(Module):
@ -92,15 +95,61 @@ class BaseSoC(SoCSDRAM):
sdram_module.geom_settings,
sdram_module.timing_settings)
# EthernetSoC ------------------------------------------------------------------------------------------
class EthernetSoC(BaseSoC):
csr_map = {
"ethphy": 18,
"ethmac": 19
}
csr_map.update(BaseSoC.csr_map)
interrupt_map = {
"ethmac": 3,
}
interrupt_map.update(BaseSoC.interrupt_map)
mem_map = {
"ethmac": 0x30000000, # (shadow @0xb0000000)
}
mem_map.update(BaseSoC.mem_map)
def __init__(self, **kwargs):
BaseSoC.__init__(self, **kwargs)
self.comb += self.platform.request("sfp_tx_disable_n", 0).eq(1)
self.submodules.ethphy = KU_1000BASEX(self.crg.cd_clk200.clk,
self.platform.request("sfp", 0), sys_clk_freq=self.clk_freq)
self.submodules.ethmac = LiteEthMAC(phy=self.ethphy, dw=32,
interface="wishbone", endianness=self.cpu.endianness)
self.add_wb_slave(mem_decoder(self.mem_map["ethmac"]), self.ethmac.bus)
self.add_memory_region("ethmac", self.mem_map["ethmac"] | self.shadow_base, 0x2000)
self.crg.cd_sys.clk.attr.add("keep")
self.ethphy.cd_eth_rx.clk.attr.add("keep")
self.ethphy.cd_eth_tx.clk.attr.add("keep")
self.platform.add_period_constraint(self.ethphy.cd_eth_rx.clk, 1e9/125e6)
self.platform.add_period_constraint(self.ethphy.cd_eth_tx.clk, 1e9/125e6)
self.platform.add_false_path_constraints(
self.crg.cd_sys.clk,
self.ethphy.cd_eth_rx.clk,
self.ethphy.cd_eth_tx.clk)
self.platform.add_platform_command("set_property SEVERITY {{Warning}} [get_drc_checks REQP-1753]")
# Build --------------------------------------------------------------------------------------------
def main():
parser = argparse.ArgumentParser(description="LiteX SoC on KCU105")
builder_args(parser)
soc_sdram_args(parser)
parser.add_argument("--with-ethernet", action="store_true",
help="enable Ethernet support")
args = parser.parse_args()
soc = BaseSoC(**soc_sdram_argdict(args))
cls = EthernetSoC if args.with_ethernet else BaseSoC
soc = cls(**soc_sdram_argdict(args))
builder = Builder(soc, **builder_argdict(args))
builder.build()

View file

@ -13,7 +13,10 @@ from litex.soc.integration.soc_sdram import *
from litex.soc.integration.builder import *
from litedram.modules import MT41K64M16
from litedram.phy import ECP5DDRPHY, ECP5DDRPHYInit
from litedram.phy import ECP5DDRPHY
from liteeth.phy.ecp5rgmii import LiteEthPHYRGMII
from liteeth.core.mac import LiteEthMAC
# CRG ----------------------------------------------------------------------------------------------
@ -70,7 +73,7 @@ class BaseSoC(SoCSDRAM):
csr_map.update(SoCSDRAM.csr_map)
def __init__(self, toolchain="diamond", **kwargs):
platform = versa_ecp5.Platform(toolchain=toolchain)
sys_clk_freq = int(50e6)
sys_clk_freq = int(75e6)
SoCSDRAM.__init__(self, platform, clk_freq=sys_clk_freq,
integrated_rom_size=0x8000,
**kwargs)
@ -84,24 +87,61 @@ class BaseSoC(SoCSDRAM):
platform.request("ddram"),
sys_clk_freq=sys_clk_freq)
self.add_constant("ECP5DDRPHY", None)
ddrphy_init = ECP5DDRPHYInit(self.crg, self.ddrphy)
self.submodules += ddrphy_init
self.comb += crg.stop.eq(self.ddrphy.init.stop)
sdram_module = MT41K64M16(sys_clk_freq, "1:2")
self.register_sdram(self.ddrphy,
sdram_module.geom_settings,
sdram_module.timing_settings)
# EthernetSoC --------------------------------------------------------------------------------------
class EthernetSoC(BaseSoC):
csr_map = {
"ethphy": 18,
"ethmac": 19
}
csr_map.update(BaseSoC.csr_map)
interrupt_map = {
"ethmac": 3,
}
interrupt_map.update(BaseSoC.interrupt_map)
mem_map = {
"ethmac": 0x30000000, # (shadow @0xb0000000)
}
mem_map.update(BaseSoC.mem_map)
def __init__(self, toolchain="diamond", **kwargs):
BaseSoC.__init__(self, toolchain=toolchain, **kwargs)
self.submodules.ethphy = LiteEthPHYRGMII(
self.platform.request("eth_clocks"),
self.platform.request("eth"))
self.submodules.ethmac = LiteEthMAC(phy=self.ethphy, dw=32,
interface="wishbone", endianness=self.cpu.endianness)
self.add_wb_slave(mem_decoder(self.mem_map["ethmac"]), self.ethmac.bus)
self.add_memory_region("ethmac", self.mem_map["ethmac"] | self.shadow_base, 0x2000)
self.ethphy.crg.cd_eth_rx.clk.attr.add("keep")
self.ethphy.crg.cd_eth_tx.clk.attr.add("keep")
self.platform.add_period_constraint(self.ethphy.crg.cd_eth_rx.clk, 1e9/125e6)
self.platform.add_period_constraint(self.ethphy.crg.cd_eth_tx.clk, 1e9/125e6)
# Build --------------------------------------------------------------------------------------------
def main():
parser = argparse.ArgumentParser(description="LiteX SoC on ECP5")
parser = argparse.ArgumentParser(description="LiteX SoC on Versa ECP5")
parser.add_argument("--gateware-toolchain", dest="toolchain", default="diamond",
help='gateware toolchain to use, diamond (default) or trellis')
builder_args(parser)
soc_sdram_args(parser)
parser.add_argument("--with-ethernet", action="store_true",
help="enable Ethernet support")
args = parser.parse_args()
soc = BaseSoC(toolchain=args.toolchain, **soc_sdram_argdict(args))
cls = EthernetSoC if args.with_ethernet else BaseSoC
soc = cls(args.toolchain, **soc_sdram_argdict(args))
builder = Builder(soc, **builder_argdict(args))
builder.build()

View file

@ -1,6 +1,9 @@
from migen.fhdl.module import Module
from migen.fhdl.specials import Instance
from migen.genlib.io import DifferentialInput, DifferentialOutput
from migen.genlib.resetsync import AsyncResetSynchronizer
from migen.fhdl.structure import *
class AlteraDifferentialInputImpl(Module):
@ -32,8 +35,29 @@ class AlteraDifferentialOutput:
def lower(dr):
return AlteraDifferentialOutputImpl(dr.i, dr.o_p, dr.o_n)
class AlteraAsyncResetSynchronizerImpl(Module):
def __init__(self, cd, async_reset):
if not hasattr(async_reset, "attr"):
i, async_reset = async_reset, Signal()
self.comb += async_reset.eq(i)
rst_meta = Signal()
self.specials += [
Instance("DFF", i_d=0, i_clk=cd.clk, i_clrn=1,
i_prn=async_reset, o_q=rst_meta,
attr={"async_reg", "ars_ff1"}),
Instance("DFF", i_d=rst_meta, i_clk=cd.clk, i_clrn=1,
i_prn=async_reset, o_q=cd.rst,
attr={"async_reg", "ars_ff2"})
]
class AlteraAsyncResetSynchronizer:
@staticmethod
def lower(dr):
return AlteraAsyncResetSynchronizerImpl(dr.cd, dr.async_reset)
altera_special_overrides = {
DifferentialInput: AlteraDifferentialInput,
DifferentialOutput: AlteraDifferentialOutput
DifferentialOutput: AlteraDifferentialOutput,
AsyncResetSynchronizer: AlteraAsyncResetSynchronizer
}

View file

@ -25,3 +25,10 @@ class AlteraPlatform(GenericPlatform):
if hasattr(clk, "p"):
clk = clk.p
self.toolchain.add_period_constraint(self, clk, period)
def add_false_path_constraint(self, from_, to):
if hasattr(from_, "p"):
from_ = from_.p
if hasattr(to, "p"):
to = to.p
self.toolchain.add_false_path_constraint(self, from_, to)

View file

@ -1,8 +1,9 @@
# This file is Copyright (c) 2013 Florent Kermarrec <florent@enjoy-digital.fr>
# This file is Copyright (c) 2013-2019 Florent Kermarrec <florent@enjoy-digital.fr>
# License: BSD
import os
import subprocess
import math
from migen.fhdl.structure import _Fragment
@ -50,7 +51,7 @@ def _format_qsf(signame, pin, others, resname):
return '\n'.join(fmt_c)
def _build_qsf(named_sc, named_pc):
def _build_qsf(named_sc, named_pc, build_name):
lines = []
for sig, pins, others, resname in named_sc:
if len(pins) > 1:
@ -64,10 +65,27 @@ def _build_qsf(named_sc, named_pc):
lines.append("")
lines.append("\n\n".join(named_pc))
lines.append("set_global_assignment -name top_level_entity top")
# Set top level name to "build_name" in .qsf file instead always use "top" name
lines.append("set_global_assignment -name top_level_entity " + build_name)
return "\n".join(lines)
def _build_sdc(clocks, false_paths, vns, build_name):
lines = []
for clk, period in sorted(clocks.items(), key=lambda x: x[0].duid):
lines.append(
"create_clock -name {clk} -period ".format(clk=vns.get_name(clk)) + str(period) +
" [get_ports {{{clk}}}]".format(clk=vns.get_name(clk)))
for from_, to in sorted(false_paths,
key=lambda x: (x[0].duid, x[1].duid)):
lines.append(
"set_false_path "
"-from [get_clocks {{{from_}}}] "
"-to [get_clocks {{{to}}}]".format(
from_=vns.get_name(from_), to=vns.get_name(to)))
tools.write_to_file("{}.sdc".format(build_name), "\n".join(lines))
def _build_files(device, sources, vincpaths, named_sc, named_pc, build_name):
lines = []
for filename, language, library in sources:
@ -81,12 +99,13 @@ def _build_files(device, sources, vincpaths, named_sc, named_pc, build_name):
lang=language.upper(),
path=filename.replace("\\", "/"),
lib=library))
lines.append("set_global_assignment -name SDC_FILE {}.sdc".format(build_name))
for path in vincpaths:
lines.append("set_global_assignment -name SEARCH_PATH {}".format(
path.replace("\\", "/")))
lines.append(_build_qsf(named_sc, named_pc))
lines.append(_build_qsf(named_sc, named_pc, build_name))
lines.append("set_global_assignment -name DEVICE {}".format(device))
tools.write_to_file("{}.qsf".format(build_name), "\n".join(lines))
@ -116,6 +135,10 @@ fi
class AlteraQuartusToolchain:
def __init__(self):
self.clocks = dict()
self.false_paths = set()
def build(self, platform, fragment, build_dir="build", build_name="top",
toolchain_path=None, run=True, **kwargs):
if toolchain_path is None:
@ -139,6 +162,8 @@ class AlteraQuartusToolchain:
named_sc,
named_pc,
build_name)
_build_sdc(self.clocks, self.false_paths, v_output.ns, build_name)
if run:
_run_quartus(build_name, toolchain_path)
@ -147,12 +172,11 @@ class AlteraQuartusToolchain:
return v_output.ns
def add_period_constraint(self, platform, clk, period):
# TODO: handle differential clk
platform.add_platform_command(
"set_global_assignment -name duty_cycle 50 -section_id {clk}",
clk=clk)
platform.add_platform_command(
"set_global_assignment -name fmax_requirement \"{freq} MHz\" "
"-section_id {clk}".format(freq=(1. / period) * 1000,
clk="{clk}"),
clk=clk)
if clk in self.clocks:
raise ValueError("A period constraint already exists")
period = math.floor(period*1e3)/1e3 # round to lowest picosecond
self.clocks[clk] = period
def add_false_path_constraint(self, platform, from_, to):
if (to, from_) not in self.false_paths:
self.false_paths.add((from_, to))

View file

@ -143,7 +143,7 @@ class LatticeTrellisToolchain:
self.build_template = [
"yosys -q -l {build_name}.rpt {build_name}.ys",
"nextpnr-ecp5 --json {build_name}.json --lpf {build_name}.lpf --textcfg {build_name}.config --{architecture} --package {package} --freq {freq_constraint}",
"ecppack {build_name}.config {build_name}.bit"
"ecppack {build_name}.config --svf {build_name}.svf --bit {build_name}.bit"
]
self.freq_constraints = dict()

View file

@ -23,6 +23,8 @@ def _format_io_constraint(c):
elif isinstance(c, IOStandard):
return "-io_std {} ".format(c.name)
elif isinstance(c, Misc):
return "-RES_PULL {} ".format(c.misc)
else:
raise NotImplementedError
@ -183,7 +185,10 @@ def _build_script(build_name, device, toolchain_path, ver=None):
copy_stmt = "copy"
fail_stmt = " || exit /b"
else:
raise NotImplementedError
script_ext = ".sh"
build_script_contents = "# Autogenerated by Migen\n\n"
copy_stmt = "cp"
fail_stmt = " || exit 1"
build_script_file = "build_" + build_name + script_ext
tools.write_to_file(build_script_file, build_script_contents,

View file

@ -203,7 +203,7 @@ static void cb(int sock, short which, void *arg)
}
}
int main()
int main(int argc, char *argv[])
{
void *vdut=NULL;
struct timeval tv;
@ -224,6 +224,7 @@ int main()
goto out;
}
litex_sim_init_cmdargs(argc, argv);
if(RC_OK != (ret = litex_sim_initialize_all(&vdut, base)))
{
goto out;

View file

@ -17,6 +17,11 @@ extern "C" void litex_sim_eval(void *vdut)
dut->eval();
}
extern "C" void litex_sim_init_cmdargs(int argc, char *argv[])
{
Verilated::commandArgs(argc, argv);
}
extern "C" void litex_sim_init_tracer(void *vdut)
{
Vdut *dut = (Vdut*)vdut;

View file

@ -4,6 +4,7 @@
#define __VERIL_H_
#ifdef __cplusplus
extern "C" void litex_sim_init_cmdargs(int argc, char *argv[]);
extern "C" void litex_sim_eval(void *vdut);
extern "C" void litex_sim_init_tracer(void *vdut);
extern "C" void litex_sim_tracer_dump();

View file

@ -265,7 +265,7 @@ setattr -set keep 1 a:async_reg=true
synth_xilinx -top top
write_edif -attrprop {build_name}.edif
write_edif -pvector bra -attrprop {build_name}.edif
""".format(build_name=build_name)
ys_name = build_name + ".ys"

View file

@ -1,9 +1,10 @@
# This file is Copyright (c) 2014 Florent Kermarrec <florent@enjoy-digital.fr>
# This file is Copyright (c) 2014-2019 Florent Kermarrec <florent@enjoy-digital.fr>
# License: BSD
import os
import subprocess
import sys
import math
from migen.fhdl.structure import _Fragment
@ -117,6 +118,7 @@ class XilinxVivadoToolchain:
for filename, language, library in sources:
filename_tcl = "{" + filename + "}"
tcl.append("add_files " + filename_tcl)
if language == "vhdl":
tcl.append("set_property library {} [get_files {}]"
.format(library, filename_tcl))
for filename in edifs:
@ -196,23 +198,23 @@ class XilinxVivadoToolchain:
# The asynchronous input to a MultiReg is a false path
platform.add_platform_command(
"set_false_path -quiet "
"-to [get_nets -filter {{mr_ff == TRUE}}]"
"-to [get_nets -quiet -filter {{mr_ff == TRUE}}]"
)
# The asychronous reset input to the AsyncResetSynchronizer is a false
# path
platform.add_platform_command(
"set_false_path -quiet "
"-to [get_pins -filter {{REF_PIN_NAME == PRE}} "
"-of [get_cells -filter {{ars_ff1 == TRUE || ars_ff2 == TRUE}}]]"
"-to [get_pins -quiet -filter {{REF_PIN_NAME == PRE}} "
"-of [get_cells -quiet -filter {{ars_ff1 == TRUE || ars_ff2 == TRUE}}]]"
)
# clock_period-2ns to resolve metastability on the wire between the
# AsyncResetSynchronizer FFs
platform.add_platform_command(
"set_max_delay 2 -quiet "
"-from [get_pins -filter {{REF_PIN_NAME == Q}} "
"-of [get_cells -filter {{ars_ff1 == TRUE}}]] "
"-to [get_pins -filter {{REF_PIN_NAME == D}} "
"-of [get_cells -filter {{ars_ff2 == TRUE}}]]"
"-from [get_pins -quiet -filter {{REF_PIN_NAME == Q}} "
"-of [get_cells -quiet -filter {{ars_ff1 == TRUE}}]] "
"-to [get_pins -quiet -filter {{REF_PIN_NAME == D}} "
"-of [get_cells -quiet -filter {{ars_ff2 == TRUE}}]]"
)
def build(self, platform, fragment, build_dir="build", build_name="top",
@ -250,6 +252,7 @@ class XilinxVivadoToolchain:
def add_period_constraint(self, platform, clk, period):
if clk in self.clocks:
raise ValueError("A period constraint already exists")
period = math.floor(period*1e3)/1e3 # round to lowest picosecond
self.clocks[clk] = period
def add_false_path_constraint(self, platform, from_, to):

View file

@ -1,9 +1,4 @@
"""
Clock Abstraction Modules
Made in Paris-CDG while waiting a delayed Air-France KLM flight...
"""
"""Clock Abstraction Modules"""
from migen import *
from migen.genlib.io import DifferentialInput
@ -15,13 +10,14 @@ from litex.soc.interconnect.csr import *
def period_ns(freq):
return 1e9/freq
# Xilinx / 7-Series
# Xilinx / 7-Series --------------------------------------------------------------------------------
class S7Clocking(Module, AutoCSR):
clkfbout_mult_frange = (2, 64+1)
clkout_divide_range = (1, 128+1)
def __init__(self):
def __init__(self, vco_margin=0):
self.vco_margin = vco_margin
self.reset = Signal()
self.locked = Signal()
self.clkin_freq = None
@ -62,12 +58,14 @@ class S7Clocking(Module, AutoCSR):
def compute_config(self):
config = {}
config["divclk_divide"] = 1
for divclk_divide in range(*self.divclk_divide_range):
config["divclk_divide"] = divclk_divide
for clkfbout_mult in range(*self.clkfbout_mult_frange):
all_valid = True
vco_freq = self.clkin_freq*clkfbout_mult
vco_freq = self.clkin_freq*clkfbout_mult/divclk_divide
(vco_freq_min, vco_freq_max) = self.vco_freq_range
if vco_freq >= vco_freq_min and vco_freq <= vco_freq_max:
if (vco_freq >= vco_freq_min*(1 + self.vco_margin) and
vco_freq <= vco_freq_max*(1 - self.vco_margin)):
for n, (clk, f, p, m) in sorted(self.clkouts.items()):
valid = False
for d in range(*self.clkout_divide_range):
@ -127,6 +125,7 @@ class S7PLL(S7Clocking):
def __init__(self, speedgrade=-1):
S7Clocking.__init__(self)
self.divclk_divide_range = (1, 56+1)
self.vco_freq_range = {
-1: (800e6, 2133e6),
-2: (800e6, 1866e6),
@ -157,6 +156,7 @@ class S7MMCM(S7Clocking):
def __init__(self, speedgrade=-1):
S7Clocking.__init__(self)
self.divclk_divide_range = (1, 106+1)
self.clkin_freq_range = {
-1: (10e6, 800e6),
-2: (10e6, 933e6),
@ -204,7 +204,7 @@ class S7IDELAYCTRL(Module):
)
self.specials += Instance("IDELAYCTRL", i_REFCLK=cd.clk, i_RST=ic_reset)
# Xilinx / Ultrascale
# Xilinx / Ultrascale ------------------------------------------------------------------------------
# TODO:
# - use Ultrascale primitives instead of 7-Series' ones. (Vivado recognize and convert them).
@ -213,7 +213,8 @@ class USClocking(Module, AutoCSR):
clkfbout_mult_frange = (2, 64+1)
clkout_divide_range = (1, 128+1)
def __init__(self):
def __init__(self, vco_margin=0):
self.vco_margin = vco_margin
self.reset = Signal()
self.locked = Signal()
self.clkin_freq = None
@ -254,12 +255,14 @@ class USClocking(Module, AutoCSR):
def compute_config(self):
config = {}
config["divclk_divide"] = 1
for divclk_divide in range(*self.divclk_divide_range):
config["divclk_divide"] = divclk_divide
for clkfbout_mult in range(*self.clkfbout_mult_frange):
all_valid = True
vco_freq = self.clkin_freq*clkfbout_mult
vco_freq = self.clkin_freq*clkfbout_mult/divclk_divide
(vco_freq_min, vco_freq_max) = self.vco_freq_range
if vco_freq >= vco_freq_min and vco_freq <= vco_freq_max:
if (vco_freq >= vco_freq_min*(1 + self.vco_margin) and
vco_freq <= vco_freq_max*(1 - self.vco_margin)):
for n, (clk, f, p, m) in sorted(self.clkouts.items()):
valid = False
for d in range(*self.clkout_divide_range):
@ -318,12 +321,12 @@ class USPLL(USClocking):
def __init__(self, speedgrade=-1):
USClocking.__init__(self)
self.divclk_divide_range = (1, 56+1)
self.clkin_freq_range = {
-1: (70e6, 800e6),
-2: (70e6, 933e6),
-3: (70e6, 1066e6),
}[speedgrade]
self.vco_freq_range = {
-1: (600e6, 1200e6),
-2: (600e6, 1335e6),
@ -354,12 +357,12 @@ class USMMCM(USClocking):
def __init__(self, speedgrade=-1):
USClocking.__init__(self)
self.divclk_divide_range = (1, 106+1)
self.clkin_freq_range = {
-1: (10e6, 800e6),
-2: (10e6, 933e6),
-3: (10e6, 1066e6),
}[speedgrade]
self.vco_freq_range = {
-1: (600e6, 1200e6),
-2: (600e6, 1440e6),
@ -404,7 +407,7 @@ class USIDELAYCTRL(Module):
i_REFCLK=cd.clk,
i_RST=ic_reset)
# Lattice / ECP5
# Lattice / ECP5 -----------------------------------------------------------------------------------
# TODO:
# - add proper phase support.

View file

@ -16,8 +16,11 @@ class VexRiscv(Module, AutoCSR):
def __init__(self, platform, cpu_reset_address, variant=None):
variant = "std" if variant is None else variant
variant = "std_debug" if variant == "debug" else variant
variants = ("std", "std_debug", "lite", "lite_debug", "min", "min_debug")
variants = ("std", "std_debug", "lite", "lite_debug", "min", "min_debug", "full", "full_debug")
assert variant in variants, "Unsupported variant %s" % variant
self.platform = platform
self.variant = variant
self.external_variant = None
self.reset = Signal()
self.ibus = ibus = wishbone.Interface()
self.dbus = dbus = wishbone.Interface()
@ -60,9 +63,6 @@ class VexRiscv(Module, AutoCSR):
if "debug" in variant:
self.add_debug()
# add verilog sources
self.add_sources(platform, variant)
def add_debug(self):
debug_reset = Signal()
@ -156,12 +156,20 @@ class VexRiscv(Module, AutoCSR):
"std_debug": "VexRiscv_Debug.v",
"lite": "VexRiscv_Lite.v",
"lite_debug": "VexRiscv_LiteDebug.v",
"min": "VexRiscv_Lite.v",
"min_debug": "VexRiscv_LiteDebug.v",
"min": "VexRiscv_Min.v",
"min_debug": "VexRiscv_MinDebug.v",
"full": "VexRiscv_Full.v",
"full_debug": "VexRiscv_FullDebug.v",
}
cpu_filename = verilog_variants[variant]
vdir = os.path.join(os.path.abspath(os.path.dirname(__file__)), "verilog")
platform.add_source(os.path.join(vdir, cpu_filename))
def use_external_variant(self, variant_filename):
self.external_variant = True
self.platform.add_source(variant_filename)
def do_finalize(self):
if not self.external_variant:
self.add_sources(self.platform, self.variant)
self.specials += Instance("VexRiscv", **self.cpu_params)

@ -1 +1 @@
Subproject commit d7bbc2c167f1a0886c446d3c305d0ed4388570be
Subproject commit ebe4064653bc143bf92a0ccdd1099173620fcbf5

View file

@ -1,5 +1,7 @@
import os
import struct
import inspect
import json
from operator import itemgetter
from migen import *
@ -36,24 +38,43 @@ def mem_decoder(address, start=26, end=29):
def get_mem_data(filename, endianness="big", mem_size=None):
data = []
with open(filename, "rb") as mem_file:
while True:
w = mem_file.read(4)
if not w:
break
if endianness == "little":
data.append(struct.unpack("<I", w)[0])
# create memory regions
_, ext = os.path.splitext(filename)
if ext == ".json":
f = open(filename, "r")
regions = json.load(f)
f.close()
else:
data.append(struct.unpack(">I", w)[0])
data_size = len(data)*4
regions = {filename: "0x00000000"}
# determine data_size
data_size = 0
for filename, base in regions.items():
data_size = max(int(base, 16) + os.path.getsize(filename), data_size)
assert data_size > 0
if mem_size is not None:
assert data_size < mem_size, (
"file is too big: {}/{} bytes".format(
data_size, mem_size))
return data
# fill data
data = [0]*(data_size//4)
for filename, base in regions.items():
with open(filename, "rb") as f:
i = 0
while True:
w = f.read(4)
if not w:
break
if len(w) != 4:
for i in range(len(w), 4):
w += b'\x00'
if endianness == "little":
data[i] = struct.unpack("<I", w)[0]
else:
data[i] = struct.unpack(">I", w)[0]
i += 1
return data
class ReadOnlyDict(dict):
def __readonly__(self, *args, **kwargs):

View file

@ -8,16 +8,29 @@ from litex.soc.integration.cpu_interface import get_csr_header
from litex.soc.interconnect import wishbone
from litex.soc.interconnect import axi
# Record layouts -----------------------------------------------------------------------------------
def axi_fifo_ctrl_layout():
return [
("racount", 3, DIR_M_TO_S),
("rcount", 8, DIR_M_TO_S),
("rdissuecapen", 1, DIR_S_TO_M),
("wacount", 6, DIR_M_TO_S),
("wcount", 8, DIR_M_TO_S),
("wrissuecapen", 1, DIR_S_TO_M),
]
# SoC Zync -----------------------------------------------------------------------------------------
class SoCZynq(SoCCore):
SoCCore.mem_map["csr"] = 0x00000000
def __init__(self, platform, clk_freq, ps7_name, **kwargs):
self.ps7_name = ps7_name
SoCCore.__init__(self, platform, clk_freq, cpu_type=None, shadow_base=0x00000000, **kwargs)
# PS7 --------------------------------------------------------------------------------------
self.axi_gp0 = axi_gp0 = axi.AXIInterface(data_width=32, address_width=32, id_width=12)
# PS7 (Minimal) ----------------------------------------------------------------------------
ps7_ddram_pads = platform.request("ps7_ddram")
self.specials += Instance(ps7_name,
self.ps7_params = dict(
# clk/rst
io_PS_CLK=platform.request("ps7_clk"),
io_PS_PORB=platform.request("ps7_porb"),
@ -57,10 +70,17 @@ class SoCZynq(SoCCore):
# fabric clk
o_FCLK_CLK0=ClockSignal("sys"),
# axi clk
# axi gp0 clk
i_M_AXI_GP0_ACLK=ClockSignal("sys"),
)
platform.add_ip(os.path.join("ip", ps7_name + ".xci"))
# axi aw
# GP0 ------------------------------------------------------------------------------------------
def add_gp0(self):
self.axi_gp0 = axi_gp0 = axi.AXIInterface(data_width=32, address_width=32, id_width=12)
self.ps7_params.update(
# axi gp0 aw
o_M_AXI_GP0_AWVALID=axi_gp0.aw.valid,
i_M_AXI_GP0_AWREADY=axi_gp0.aw.ready,
o_M_AXI_GP0_AWADDR=axi_gp0.aw.addr,
@ -68,39 +88,39 @@ class SoCZynq(SoCCore):
o_M_AXI_GP0_AWLEN=axi_gp0.aw.len,
o_M_AXI_GP0_AWSIZE=axi_gp0.aw.size,
o_M_AXI_GP0_AWID=axi_gp0.aw.id,
#o_M_AXI_GP0_AWLOCK =,
#o_M_AXI_GP0_AWPROT =,
#o_M_AXI_GP0_AWCACHE =,
#o_M_AXI_GP0_AWQOS =,
o_M_AXI_GP0_AWLOCK=axi_gp0.aw.lock,
o_M_AXI_GP0_AWPROT=axi_gp0.aw.prot,
o_M_AXI_GP0_AWCACHE=axi_gp0.aw.cache,
o_M_AXI_GP0_AWQOS=axi_gp0.aw.qos,
# axi w
# axi gp0 w
o_M_AXI_GP0_WVALID=axi_gp0.w.valid,
o_M_AXI_GP0_WLAST=axi_gp0.w.last,
i_M_AXI_GP0_WREADY=axi_gp0.w.ready,
#o_M_AXI_GP0_WID=,
o_M_AXI_GP0_WID=axi_gp0.w.id,
o_M_AXI_GP0_WDATA=axi_gp0.w.data,
o_M_AXI_GP0_WSTRB=axi_gp0.w.strb,
# axi b
# axi gp0 b
i_M_AXI_GP0_BVALID=axi_gp0.b.valid,
o_M_AXI_GP0_BREADY=axi_gp0.b.ready,
i_M_AXI_GP0_BID=axi_gp0.b.id,
i_M_AXI_GP0_BRESP=axi_gp0.b.resp,
# axi ar
# axi gp0 ar
o_M_AXI_GP0_ARVALID=axi_gp0.ar.valid,
i_M_AXI_GP0_ARREADY=axi_gp0.ar.ready,
o_M_AXI_GP0_ARADDR=axi_gp0.ar.addr,
o_M_AXI_GP0_ARBURST=axi_gp0.ar.burst,
o_M_AXI_GP0_ARLEN=axi_gp0.ar.len,
o_M_AXI_GP0_ARID=axi_gp0.ar.id,
#o_M_AXI_GP0_ARLOCK=,
#o_M_AXI_GP0_ARSIZE=,
#o_M_AXI_GP0_ARPROT=,
#o_M_AXI_GP0_ARCACHE=,
#o_M_AXI_GP0_ARQOS=,
o_M_AXI_GP0_ARLOCK=axi_gp0.ar.lock,
o_M_AXI_GP0_ARSIZE=axi_gp0.ar.size,
o_M_AXI_GP0_ARPROT=axi_gp0.ar.prot,
o_M_AXI_GP0_ARCACHE=axi_gp0.ar.cache,
o_M_AXI_GP0_ARQOS=axi_gp0.ar.qos,
# axi r
# axi gp0 r
i_M_AXI_GP0_RVALID=axi_gp0.r.valid,
o_M_AXI_GP0_RREADY=axi_gp0.r.ready,
i_M_AXI_GP0_RLAST=axi_gp0.r.last,
@ -108,13 +128,79 @@ class SoCZynq(SoCCore):
i_M_AXI_GP0_RRESP=axi_gp0.r.resp,
i_M_AXI_GP0_RDATA=axi_gp0.r.data,
)
platform.add_ip(os.path.join("ip", ps7_name + ".xci"))
# AXI to Wishbone --------------------------------------------------------------------------
self.wb_gp0 = wb_gp0 = wishbone.Interface()
axi2wishbone = axi.AXI2Wishbone(axi_gp0, wb_gp0, base_address=0x43c00000)
# HP0 ------------------------------------------------------------------------------------------
def add_hp0(self):
self.axi_hp0 = axi_hp0 = axi.AXIInterface(data_width=64, address_width=32, id_width=6)
self.axi_hp0_fifo_ctrl = axi_hp0_fifo_ctrl = Record(axi_fifo_ctrl_layout())
self.ps7_params.update(
# axi hp0 aw
i_S_AXI_HP0_AWVALID=axi_hp0.aw.valid,
o_S_AXI_HP0_AWREADY=axi_hp0.aw.ready,
i_S_AXI_HP0_AWADDR=axi_hp0.aw.addr,
i_S_AXI_HP0_AWBURST=axi_hp0.aw.burst,
i_S_AXI_HP0_AWLEN=axi_hp0.aw.len,
i_S_AXI_HP0_AWSIZE=axi_hp0.aw.size,
i_S_AXI_HP0_AWID=axi_hp0.aw.id,
i_S_AXI_HP0_AWLOCK=axi_hp0.aw.lock,
i_S_AXI_HP0_AWPROT=axi_hp0.aw.prot,
i_S_AXI_HP0_AWCACHE=axi_hp0.aw.cache,
i_S_AXI_HP0_AWQOS=axi_hp0.aw.qos,
# axi hp0 w
i_S_AXI_HP0_WVALID=axi_hp0.w.valid,
i_S_AXI_HP0_WLAST=axi_hp0.w.last,
o_S_AXI_HP0_WREADY=axi_hp0.w.ready,
i_S_AXI_HP0_WID=axi_hp0.w.id,
i_S_AXI_HP0_WDATA=axi_hp0.w.data,
i_S_AXI_HP0_WSTRB=axi_hp0.w.strb,
# axi hp0 b
o_S_AXI_HP0_BVALID=axi_hp0.b.valid,
i_S_AXI_HP0_BREADY=axi_hp0.b.ready,
o_S_AXI_HP0_BID=axi_hp0.b.id,
o_S_AXI_HP0_BRESP=axi_hp0.b.resp,
# axi hp0 ar
i_S_AXI_HP0_ARVALID=axi_hp0.ar.valid,
o_S_AXI_HP0_ARREADY=axi_hp0.ar.ready,
i_S_AXI_HP0_ARADDR=axi_hp0.ar.addr,
i_S_AXI_HP0_ARBURST=axi_hp0.ar.burst,
i_S_AXI_HP0_ARLEN=axi_hp0.ar.len,
i_S_AXI_HP0_ARID=axi_hp0.ar.id,
i_S_AXI_HP0_ARLOCK=axi_hp0.ar.lock,
i_S_AXI_HP0_ARSIZE=axi_hp0.ar.size,
i_S_AXI_HP0_ARPROT=axi_hp0.ar.prot,
i_S_AXI_HP0_ARCACHE=axi_hp0.ar.cache,
i_S_AXI_HP0_ARQOS=axi_hp0.ar.qos,
# axi hp0 r
o_S_AXI_HP0_RVALID=axi_hp0.r.valid,
i_S_AXI_HP0_RREADY=axi_hp0.r.ready,
o_S_AXI_HP0_RLAST=axi_hp0.r.last,
o_S_AXI_HP0_RID=axi_hp0.r.id,
o_S_AXI_HP0_RRESP=axi_hp0.r.resp,
o_S_AXI_HP0_RDATA=axi_hp0.r.data,
# axi hp0 fifo ctrl
o_S_AXI_HP0_RACOUNT=axi_hp0_fifo_ctrl.racount,
o_S_AXI_HP0_RCOUNT=axi_hp0_fifo_ctrl.rcount,
i_S_AXI_HP0_RDISSUECAP1_EN=axi_hp0_fifo_ctrl.rdissuecapen,
o_S_AXI_HP0_WACOUNT=axi_hp0_fifo_ctrl.wacount,
o_S_AXI_HP0_WCOUNT=axi_hp0_fifo_ctrl.wcount,
i_S_AXI_HP0_WRISSUECAP1_EN=axi_hp0_fifo_ctrl.wrissuecapen
)
def add_axi_to_wishbone(self, axi_port, base_address=0x43c00000):
wb = wishbone.Interface()
axi2wishbone = axi.AXI2Wishbone(axi_port, wb, base_address)
self.submodules += axi2wishbone
self.add_wb_master(wb_gp0)
self.add_wb_master(wb)
def do_finalize(self):
SoCCore.do_finalize(self)
self.specials += Instance(self.ps7_name, **self.ps7_params)
def generate_software_header(self, filename):
csr_header = get_csr_header(self.get_csr_regions(),

View file

@ -0,0 +1,38 @@
from migen import *
from litex.soc.interconnect import stream
# AvalonST to/from Native --------------------------------------------------------------------------
class Native2AvalonST(Module):
def __init__(self, layout, latency=2):
self.sink = sink = stream.Endpoint(layout)
self.source = source = stream.Endpoint(layout)
# # #
_from = sink
for n in range(latency):
_to = stream.Endpoint(layout)
self.sync += _from.connect(_to, omit={"ready"})
if n == 0:
self.sync += _to.valid.eq(sink.valid & source.ready)
_from = _to
self.comb += _to.connect(source, omit={"ready"})
self.comb += sink.ready.eq(source.ready)
class AvalonST2Native(Module):
def __init__(self, layout, latency=2):
self.sink = sink = stream.Endpoint(layout)
self.source = source = stream.Endpoint(layout)
# # #
buf = stream.SyncFIFO(layout, max(latency, 4))
self.submodules += buf
self.comb += [
sink.connect(buf.sink, omit={"ready"}),
sink.ready.eq(source.ready),
buf.source.connect(source)
]

View file

@ -20,13 +20,18 @@ def ax_description(address_width, id_width):
("burst", 2), # Burst type
("len", 8), # Number of data (-1) transfers (up to 256)
("size", 4), # Number of bytes (-1) of each data transfer (up to 1024 bits)
("lock", 2),
("prot", 3),
("cache", 4),
("qos", 4),
("id", id_width)
]
def w_description(data_width):
def w_description(data_width, id_width):
return [
("data", data_width),
("strb", data_width//8)
("strb", data_width//8),
("id", id_width)
]
def b_description(id_width):
@ -51,7 +56,7 @@ class AXIInterface(Record):
self.clock_domain = clock_domain
self.aw = stream.Endpoint(ax_description(address_width, id_width))
self.w = stream.Endpoint(w_description(data_width))
self.w = stream.Endpoint(w_description(data_width, id_width))
self.b = stream.Endpoint(b_description(id_width))
self.ar = stream.Endpoint(ax_description(address_width, id_width))
self.r = stream.Endpoint(r_description(data_width, id_width))
@ -60,12 +65,12 @@ class AXIInterface(Record):
class AXI2Wishbone(Module):
def __init__(self, axi, wishbone, base_address):
assert axi.data_width == 32
assert axi.address_width == 32
assert axi.data_width == len(wishbone.dat_r)
assert axi.address_width == len(wishbone.adr) + 2
_data = Signal(axi.data_width)
_read_addr = Signal(32)
_write_addr = Signal(32)
_read_addr = Signal(axi.address_width)
_write_addr = Signal(axi.address_width)
self.comb += _read_addr.eq(axi.ar.addr - base_address)
self.comb += _write_addr.eq(axi.aw.addr - base_address)
@ -78,8 +83,6 @@ class AXI2Wishbone(Module):
NextState("DO-WRITE")
)
)
axi_ar_addr = Signal(32)
self.comb += axi_ar_addr.eq(axi.ar.addr - base_address)
fsm.act("DO-READ",
wishbone.stb.eq(1),
wishbone.cyc.eq(1),

View file

@ -186,133 +186,18 @@ static void ident(void)
printf("Ident: %s\n", buffer);
}
#ifdef __lm32__
enum {
CSR_IE = 1, CSR_IM, CSR_IP, CSR_ICC, CSR_DCC, CSR_CC, CSR_CFG, CSR_EBA,
CSR_DC, CSR_DEBA, CSR_JTX, CSR_JRX, CSR_BP0, CSR_BP1, CSR_BP2, CSR_BP3,
CSR_WP0, CSR_WP1, CSR_WP2, CSR_WP3,
};
/* processor registers */
static int parse_csr(const char *csr)
{
if(!strcmp(csr, "ie")) return CSR_IE;
if(!strcmp(csr, "im")) return CSR_IM;
if(!strcmp(csr, "ip")) return CSR_IP;
if(!strcmp(csr, "icc")) return CSR_ICC;
if(!strcmp(csr, "dcc")) return CSR_DCC;
if(!strcmp(csr, "cc")) return CSR_CC;
if(!strcmp(csr, "cfg")) return CSR_CFG;
if(!strcmp(csr, "eba")) return CSR_EBA;
if(!strcmp(csr, "dc")) return CSR_DC;
if(!strcmp(csr, "deba")) return CSR_DEBA;
if(!strcmp(csr, "jtx")) return CSR_JTX;
if(!strcmp(csr, "jrx")) return CSR_JRX;
if(!strcmp(csr, "bp0")) return CSR_BP0;
if(!strcmp(csr, "bp1")) return CSR_BP1;
if(!strcmp(csr, "bp2")) return CSR_BP2;
if(!strcmp(csr, "bp3")) return CSR_BP3;
if(!strcmp(csr, "wp0")) return CSR_WP0;
if(!strcmp(csr, "wp1")) return CSR_WP1;
if(!strcmp(csr, "wp2")) return CSR_WP2;
if(!strcmp(csr, "wp3")) return CSR_WP3;
return 0;
}
static void rcsr(char *csr)
{
unsigned int csr2;
register unsigned int value;
if(*csr == 0) {
printf("rcsr <csr>\n");
return;
}
csr2 = parse_csr(csr);
if(csr2 == 0) {
printf("incorrect csr\n");
return;
}
switch(csr2) {
case CSR_IE: asm volatile ("rcsr %0,ie":"=r"(value)); break;
case CSR_IM: asm volatile ("rcsr %0,im":"=r"(value)); break;
case CSR_IP: asm volatile ("rcsr %0,ip":"=r"(value)); break;
case CSR_CC: asm volatile ("rcsr %0,cc":"=r"(value)); break;
case CSR_CFG: asm volatile ("rcsr %0,cfg":"=r"(value)); break;
case CSR_EBA: asm volatile ("rcsr %0,eba":"=r"(value)); break;
case CSR_DEBA: asm volatile ("rcsr %0,deba":"=r"(value)); break;
case CSR_JTX: asm volatile ("rcsr %0,jtx":"=r"(value)); break;
case CSR_JRX: asm volatile ("rcsr %0,jrx":"=r"(value)); break;
default: printf("csr write only\n"); return;
}
printf("%08x\n", value);
}
static void wcsr(char *csr, char *value)
{
char *c;
unsigned int csr2;
register unsigned int value2;
if((*csr == 0) || (*value == 0)) {
printf("wcsr <csr> <address>\n");
return;
}
csr2 = parse_csr(csr);
if(csr2 == 0) {
printf("incorrect csr\n");
return;
}
value2 = strtoul(value, &c, 0);
if(*c != 0) {
printf("incorrect value\n");
return;
}
switch(csr2) {
case CSR_IE: asm volatile ("wcsr ie,%0"::"r"(value2)); break;
case CSR_IM: asm volatile ("wcsr im,%0"::"r"(value2)); break;
case CSR_ICC: asm volatile ("wcsr icc,%0"::"r"(value2)); break;
case CSR_DCC: asm volatile ("wcsr dcc,%0"::"r"(value2)); break;
case CSR_EBA: asm volatile ("wcsr eba,%0"::"r"(value2)); break;
case CSR_DC: asm volatile ("wcsr dcc,%0"::"r"(value2)); break;
case CSR_DEBA: asm volatile ("wcsr deba,%0"::"r"(value2)); break;
case CSR_JTX: asm volatile ("wcsr jtx,%0"::"r"(value2)); break;
case CSR_JRX: asm volatile ("wcsr jrx,%0"::"r"(value2)); break;
case CSR_BP0: asm volatile ("wcsr bp0,%0"::"r"(value2)); break;
case CSR_BP1: asm volatile ("wcsr bp1,%0"::"r"(value2)); break;
case CSR_BP2: asm volatile ("wcsr bp2,%0"::"r"(value2)); break;
case CSR_BP3: asm volatile ("wcsr bp3,%0"::"r"(value2)); break;
case CSR_WP0: asm volatile ("wcsr wp0,%0"::"r"(value2)); break;
case CSR_WP1: asm volatile ("wcsr wp1,%0"::"r"(value2)); break;
case CSR_WP2: asm volatile ("wcsr wp2,%0"::"r"(value2)); break;
case CSR_WP3: asm volatile ("wcsr wp3,%0"::"r"(value2)); break;
default: printf("csr read only\n"); return;
}
}
#endif /* __lm32__ */
/* Init + command line */
static void help(void)
{
puts("LiteX SoC BIOS");
puts("Available commands:");
puts("LiteX BIOS, available commands:");
puts("mr - read address space");
puts("mw - write address space");
puts("mc - copy address space");
puts("");
puts("crc - compute CRC32 of a part of the address space");
puts("ident - display identifier");
#ifdef __lm32__
puts("rcsr - read processor CSR");
puts("wcsr - write processor CSR");
#endif
puts("");
#ifdef CSR_CTRL_BASE
puts("reboot - reset processor");
#endif
@ -326,6 +211,7 @@ static void help(void)
#ifdef ROM_BOOT_ADDRESS
puts("romboot - boot from embedded rom");
#endif
puts("");
#ifdef CSR_SDRAM_BASE
puts("memtest - run a memory test");
#endif
@ -385,11 +271,6 @@ static void do_command(char *c)
else if(strcmp(token, "help") == 0) help();
#ifdef __lm32__
else if(strcmp(token, "rcsr") == 0) rcsr(get_token(&c));
else if(strcmp(token, "wcsr") == 0) wcsr(get_token(&c), get_token(&c));
#endif
#ifdef CSR_SDRAM_BASE
else if(strcmp(token, "sdrrow") == 0) sdrrow(get_token(&c));
else if(strcmp(token, "sdrsw") == 0) sdrsw();
@ -399,6 +280,7 @@ static void do_command(char *c)
else if(strcmp(token, "sdrrderr") == 0) sdrrderr(get_token(&c));
else if(strcmp(token, "sdrwr") == 0) sdrwr(get_token(&c));
#ifdef CSR_DDRPHY_BASE
else if(strcmp(token, "sdrinit") == 0) sdrinit();
#ifdef CSR_DDRPHY_WLEVEL_EN_ADDR
else if(strcmp(token, "sdrwlon") == 0) sdrwlon();
else if(strcmp(token, "sdrwloff") == 0) sdrwloff();
@ -406,7 +288,6 @@ static void do_command(char *c)
else if(strcmp(token, "sdrlevel") == 0) sdrlevel();
#endif
else if(strcmp(token, "memtest") == 0) memtest();
else if(strcmp(token, "sdrinit") == 0) sdrinit();
#endif
else if(strcmp(token, "") != 0)
@ -509,12 +390,22 @@ int main(int i, char **c)
irq_setmask(0);
irq_setie(1);
uart_init();
printf("\n");
printf("\e[1m __ _ __ _ __\e[0m\n");
printf("\e[1m / / (_) /____ | |/_/\e[0m\n");
printf("\e[1m / /__/ / __/ -_)> <\e[0m\n");
printf("\e[1m /____/_/\\__/\\__/_/|_|\e[0m\n");
printf("\e[1m SoC BIOS / CPU: ");
printf("\n");
printf(" (c) Copyright 2012-2019 Enjoy-Digital\n");
printf(" (c) Copyright 2012-2015 M-Labs Ltd\n");
printf("\n");
printf(" BIOS built on "__DATE__" "__TIME__"\n");
crcbios();
printf("\n");
printf("--============ \e[1mSoC info\e[0m ================--\n");
printf("\e[1mCPU\e[0m: ");
#ifdef __lm32__
printf("LM32");
#elif __or1k__
@ -528,14 +419,19 @@ int main(int i, char **c)
#else
printf("Unknown");
#endif
printf(" / %3dMHz\e[0m\n", SYSTEM_CLOCK_FREQUENCY/1000000);
printf(" @ %dMHz\n", SYSTEM_CLOCK_FREQUENCY/1000000);
printf("\e[1mROM\e[0m: %dKB\n", ROM_SIZE/1024);
printf("\e[1mSRAM\e[0m: %dKB\n", SRAM_SIZE/1024);
#ifdef L2_SIZE
printf("\e[1mL2\e[0m: %dKB\n", L2_SIZE/1024);
#endif
#ifdef MAIN_RAM_SIZE
printf("\e[1mMAIN-RAM\e[0m: %dKB\n", MAIN_RAM_SIZE/1024);
#endif
printf("\n");
puts(
"(c) Copyright 2012-2018 Enjoy-Digital\n"
"(c) Copyright 2007-2018 M-Labs Limited\n"
"Built "__DATE__" "__TIME__"\n");
crcbios();
#ifdef CSR_ETHMAC_BASE
printf("--========= \e[1mPeripherals init\e[0m ===========--\n");
#ifdef CSR_ETHPHY_CRG_RESET_ADDR
eth_init();
#endif
#ifdef CSR_SDRAM_BASE
@ -547,11 +443,17 @@ int main(int i, char **c)
sdr_ok = 1;
#endif
#endif
if(sdr_ok)
boot_sequence();
else
if (sdr_ok !=1)
printf("Memory initialization failed\n");
printf("\n");
if(sdr_ok) {
printf("--========== \e[1mBoot sequence\e[0m =============--\n");
boot_sequence();
printf("\n");
}
printf("--============= \e[1mConsole\e[0m ================--\n");
while(1) {
putsnonl("\e[1mBIOS>\e[0m ");
readstr(buffer, 64);

View file

@ -17,7 +17,7 @@
#define MAIN_RAM_BASE SRAM_BASE
#endif
static void cdelay(int i)
__attribute__((unused)) static void cdelay(int i)
{
while(i > 0) {
#if defined (__lm32__)
@ -210,16 +210,18 @@ void sdrwr(char *startaddr)
#if defined (USDDRPHY)
#define ERR_DDRPHY_DELAY 512
#define ERR_DDRPHY_BITSLIP 8
#define NBMODULES DFII_PIX_DATA_SIZE/2
#elif defined (ECP5DDRPHY)
#define ERR_DDRPHY_DELAY 8
#define ERR_DDRPHY_BITSLIP 1
#define NBMODULES DFII_PIX_DATA_SIZE/4
#else
#define ERR_DDRPHY_DELAY 32
#define ERR_DDRPHY_BITSLIP 8
#define NBMODULES DFII_PIX_DATA_SIZE/2
#endif
#define ERR_DDRPHY_BITSLIP DFII_NPHASES*2
#define NBMODULES DFII_PIX_DATA_SIZE*DFII_NPHASES/8
#ifdef CSR_DDRPHY_WLEVEL_EN_ADDR
void sdrwlon(void)
@ -461,6 +463,9 @@ static int read_level_scan(int module, int bitslip)
int show = 1;
#ifdef USDDRPHY
show = (j%16 == 0);
#endif
#ifdef ECP5DDRPHY
ddrphy_burstdet_clr_write(1);
#endif
command_prd(DFII_COMMAND_CAS|DFII_COMMAND_CS|DFII_COMMAND_RDDATA);
cdelay(15);
@ -471,6 +476,10 @@ static int read_level_scan(int module, int bitslip)
if(MMPTR(sdram_dfii_pix_rddata_addr[p]+4*(2*NBMODULES-module-1)) != prs[DFII_PIX_DATA_SIZE*p+2*NBMODULES-module-1])
working = 0;
}
#ifdef ECP5DDRPHY
if (((ddrphy_burstdet_seen_read() >> module) & 0x1) != 1)
working = 0;
#endif
if (show)
printf("%d", working);
score += working;
@ -526,6 +535,9 @@ static void read_level(int module)
delay = 0;
read_delay_rst(module);
while(1) {
#ifdef ECP5DDRPHY
ddrphy_burstdet_clr_write(1);
#endif
command_prd(DFII_COMMAND_CAS|DFII_COMMAND_CS|DFII_COMMAND_RDDATA);
cdelay(15);
working = 1;
@ -535,6 +547,10 @@ static void read_level(int module)
if(MMPTR(sdram_dfii_pix_rddata_addr[p]+4*(2*NBMODULES-module-1)) != prs[DFII_PIX_DATA_SIZE*p+2*NBMODULES-module-1])
working = 0;
}
#ifdef ECP5DDRPHY
if (((ddrphy_burstdet_seen_read() >> module) & 0x1) != 1)
working = 0;
#endif
if(working)
break;
delay++;
@ -557,6 +573,9 @@ static void read_level(int module)
/* Find largest working delay */
while(1) {
#ifdef ECP5DDRPHY
ddrphy_burstdet_clr_write(1);
#endif
command_prd(DFII_COMMAND_CAS|DFII_COMMAND_CS|DFII_COMMAND_RDDATA);
cdelay(15);
working = 1;
@ -566,6 +585,10 @@ static void read_level(int module)
if(MMPTR(sdram_dfii_pix_rddata_addr[p]+4*(2*NBMODULES-module-1)) != prs[DFII_PIX_DATA_SIZE*p+2*NBMODULES-module-1])
working = 0;
}
#ifdef ECP5DDRPHY
if (((ddrphy_burstdet_seen_read() >> module) & 0x1) != 1)
working = 0;
#endif
if(!working)
break;
delay++;

View file

@ -1,11 +0,0 @@
#ifndef __HW_ETHMAC_MEM_H
#define __HW_ETHMAC_MEM_H
#include <generated/mem.h>
#define ETHMAC_RX0_BASE ETHMAC_BASE
#define ETHMAC_RX1_BASE (ETHMAC_BASE+0x0800)
#define ETHMAC_TX0_BASE (ETHMAC_BASE+0x1000)
#define ETHMAC_TX1_BASE (ETHMAC_BASE+0x1800)
#endif

View file

@ -1,4 +1,6 @@
#include <generated/csr.h>
#include <generated/mem.h>
#ifdef CSR_ETHMAC_BASE
#include <stdio.h>
@ -6,7 +8,6 @@
#include <system.h>
#include <crc.h>
#include <hw/flags.h>
#include <hw/ethmac_mem.h>
#include <net/microudp.h>
@ -110,24 +111,17 @@ struct ethernet_frame {
typedef union {
struct ethernet_frame frame;
unsigned char raw[1532];
unsigned char raw[ETHMAC_SLOT_SIZE];
} ethernet_buffer;
static unsigned int rxslot;
static unsigned int rxlen;
static ethernet_buffer *rxbuffer;
static ethernet_buffer *rxbuffer0;
static ethernet_buffer *rxbuffer1;
static unsigned int txslot;
static unsigned int txlen;
static ethernet_buffer *txbuffer;
static ethernet_buffer *txbuffer0;
static ethernet_buffer *txbuffer1;
static void send_packet(void)
{
unsigned int txslot;
#ifndef HW_PREAMBLE_CRC
unsigned int crc;
crc = crc32(&txbuffer->raw[8], txlen-8);
@ -147,15 +141,13 @@ static void send_packet(void)
printf("\n");
#endif
ethmac_sram_reader_slot_write(txslot);
ethmac_sram_reader_length_write(txlen);
while(!(ethmac_sram_reader_ready_read()));
ethmac_sram_reader_start_write(1);
txslot = (txslot+1)%2;
if (txslot)
txbuffer = txbuffer1;
else
txbuffer = txbuffer0;
while(!(ethmac_sram_reader_ready_read()));
txslot = ethmac_sram_reader_slot_read();
txbuffer = (ethernet_buffer *)(ETHMAC_BASE + ETHMAC_SLOT_SIZE * (ETHMAC_RX_SLOTS + txslot));
txslot = (txslot+1)%ETHMAC_TX_SLOTS;
ethmac_sram_reader_slot_write(txslot);
}
static unsigned char my_mac[6];
@ -415,17 +407,6 @@ void microudp_start(const unsigned char *macaddr, unsigned int ip)
ethmac_sram_reader_ev_pending_write(ETHMAC_EV_SRAM_READER);
ethmac_sram_writer_ev_pending_write(ETHMAC_EV_SRAM_WRITER);
rxbuffer0 = (ethernet_buffer *)ETHMAC_RX0_BASE;
rxbuffer1 = (ethernet_buffer *)ETHMAC_RX1_BASE;
txbuffer0 = (ethernet_buffer *)ETHMAC_TX0_BASE;
txbuffer1 = (ethernet_buffer *)ETHMAC_TX1_BASE;
rxslot = 0;
txslot = 0;
rxbuffer = rxbuffer0;
txbuffer = txbuffer0;
for(i=0;i<6;i++)
my_mac[i] = macaddr[i];
my_ip = ip;
@ -434,18 +415,21 @@ void microudp_start(const unsigned char *macaddr, unsigned int ip)
for(i=0;i<6;i++)
cached_mac[i] = 0;
ethmac_sram_reader_slot_write(0);
txbuffer = (ethernet_buffer *)(ETHMAC_BASE + ETHMAC_SLOT_SIZE * ETHMAC_RX_SLOTS);
rxbuffer = (ethernet_buffer *)ETHMAC_BASE;
rx_callback = (udp_callback)0;
}
void microudp_service(void)
{
unsigned int rxslot;
if(ethmac_sram_writer_ev_pending_read() & ETHMAC_EV_SRAM_WRITER) {
rxslot = ethmac_sram_writer_slot_read();
rxbuffer = (ethernet_buffer *)(ETHMAC_BASE + ETHMAC_SLOT_SIZE * rxslot);
rxlen = ethmac_sram_writer_length_read();
if (rxslot)
rxbuffer = rxbuffer1;
else
rxbuffer = rxbuffer0;
process_frame();
ethmac_sram_writer_ev_pending_write(ETHMAC_EV_SRAM_WRITER);
}
@ -463,13 +447,12 @@ static void busy_wait(unsigned int ds)
void eth_init(void)
{
ethphy_crg_reset_write(0);
busy_wait(2);
/* that pesky ethernet PHY needs two resets at times... */
#ifdef CSR_ETHPHY_CRG_RESET_ADDR
ethphy_crg_reset_write(1);
busy_wait(2);
ethphy_crg_reset_write(0);
busy_wait(2);
#endif
}
#ifdef CSR_ETHPHY_MODE_DETECTION_MODE_ADDR

1
litex/utils/__init__.py Normal file
View file

@ -0,0 +1 @@

View file

@ -1,5 +1,7 @@
#!/usr/bin/env python3
import argparse
import sys
import socket
import time
@ -10,22 +12,19 @@ from litex.soc.tools.remote.etherbone import EtherboneIPC
class RemoteServer(EtherboneIPC):
def __init__(self, comm, port=1234):
def __init__(self, comm, bind_ip, bind_port=1234):
self.comm = comm
self.port = port
self.bind_ip = bind_ip
self.bind_port = bind_port
self.lock = False
def open(self):
if hasattr(self, "socket"):
return
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
for i in range(32):
try:
self.socket.bind(("localhost", self.port + i))
break
except:
pass
print("tcp port: {:d}".format(self.port + i))
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
self.socket.bind((self.bind_ip, self.bind_port))
print("tcp port: {:d}".format(self.bind_port))
self.socket.listen(1)
self.comm.open()
@ -95,46 +94,65 @@ class RemoteServer(EtherboneIPC):
def main():
print("LiteX remote server")
if len(sys.argv) < 2 or len(sys.argv) > 4:
print("usages:")
print("litex_server uart [port] [baudrate]")
print("litex_server udp [server] [server_port]")
print("litex_server pcie [bar]")
sys.exit()
comm = sys.argv[1]
if comm == "uart":
parser = argparse.ArgumentParser()
# Common arguments
parser.add_argument("--bind-ip", default="localhost",
help="Host bind address")
parser.add_argument("--bind-port", default=1234,
help="Host bind port")
# UART arguments
parser.add_argument("--uart", action="store_true",
help="Select UART interface")
parser.add_argument("--uart-port", default=None,
help="Set UART port")
parser.add_argument("--uart-baudrate", default=115200,
help="Set UART baudrate")
# 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")
parser.add_argument("--udp-port", default=1234,
help="Set UDP remote port")
# PCIe arguments
parser.add_argument("--pcie", action="store_true",
help="Select PCIe interface")
parser.add_argument("--pcie-bar", default=None,
help="Set PCIe BAR")
args = parser.parse_args()
if args.uart:
from litex.soc.tools.remote import CommUART
uart_port = None
uart_baudrate = 115200
if len(sys.argv) > 2:
uart_port = sys.argv[2]
if len(sys.argv) > 3:
uart_baudrate = int(float(sys.argv[3]))
if args.uart_port is None:
print("Need to specify --uart-port, exiting.")
exit()
uart_port = args.uart_port
uart_baudrate = int(float(args.uart_baudrate))
print("[CommUART] port: {} / baudrate: {} / ".format(uart_port, uart_baudrate), end="")
comm = CommUART(uart_port, uart_baudrate)
elif comm == "udp":
elif args.udp:
from litex.soc.tools.remote import CommUDP
server = "192.168.1.50"
server_port = 1234
if len(sys.argv) > 2:
server = sys.argv[2]
if len(sys.argv) > 3:
server_port = int(sys.argv[3])
print("[CommUDP] server: {} / port: {} / ".format(server, server_port), end="")
comm = CommUDP(server, server_port)
elif comm == "pcie":
udp_ip = args.udp_ip
udp_port = int(args.udp_port)
print("[CommUDP] ip: {} / port: {} / ".format(udp_ip, udp_port), end="")
comm = CommUDP(udp_ip, udp_port)
elif args.pcie:
from litex.soc.tools.remote import CommPCIe
bar = ""
if len(sys.argv) > 2:
bar = sys.argv[2]
if len(sys.argv) > 3:
bar_size = int(sys.argv[3])
print("[CommPCIe] bar: {} / ".format(bar), end="")
comm = CommPCIe(bar)
pcie_bar = args.pcie_bar
if args.pcie_bar is None:
print("Need to speficy --pcie-bar, exiting.")
exit()
print("[CommPCIe] bar: {} / ".format(args.pcie_bar), end="")
comm = CommPCIe(args.pcie_bar)
else:
raise NotImplementedError
parser.print_help()
exit()
server = RemoteServer(comm)
server = RemoteServer(comm, args.bind_ip, int(args.bind_port))
server.open()
server.start(4)
try:

View file

@ -215,14 +215,20 @@ def main():
sim_config = SimConfig(default_clk="sys_clk")
sim_config.add_module("serial2console", "serial")
cpu_endianness = "big"
if "cpu_type" in soc_kwargs:
if soc_kwargs["cpu_type"] in ["picorv32", "vexriscv"]:
cpu_endianness = "little"
if args.rom_init:
soc_kwargs["integrated_rom_init"] = get_mem_data(args.rom_init)
soc_kwargs["integrated_rom_init"] = get_mem_data(args.rom_init, cpu_endianness)
if not args.with_sdram:
soc_kwargs["integrated_main_ram_size"] = 0x10000
soc_kwargs["integrated_main_ram_size"] = 0x10000000 # 256 MB
if args.ram_init is not None:
soc_kwargs["integrated_main_ram_init"] = get_mem_data(args.ram_init)
soc_kwargs["integrated_main_ram_size"] = max(len(soc_kwargs["integrated_main_ram_init"]), 0x10000)
soc_kwargs["integrated_main_ram_init"] = get_mem_data(args.ram_init, cpu_endianness)
else:
assert args.ram_init is None
soc_kwargs["integrated_main_ram_size"] = 0x0
if args.with_ethernet:
sim_config.add_module("ethernet", "eth", args={"interface": "tap0", "ip": "192.168.1.100"})
@ -235,6 +241,8 @@ def main():
with_etherbone=args.with_etherbone,
with_analyzer=args.with_analyzer,
**soc_kwargs)
if args.ram_init is not None:
soc.add_constant("ROM_BOOT_ADDRESS", 0x40000000)
builder_kwargs["csr_csv"] = "csr.csv"
builder = Builder(soc, **builder_kwargs)
vns = builder.build(run=False, threads=args.threads, sim_config=sim_config, trace=args.trace)

View file

@ -15,6 +15,7 @@ repos = [
("liteusb", ("http://github.com/enjoy-digital/", False, True)),
("litedram", ("http://github.com/enjoy-digital/", False, True)),
("litepcie", ("http://github.com/enjoy-digital/", False, True)),
("litesata", ("http://github.com/enjoy-digital/", False, True)),
("litesdcard", ("http://github.com/enjoy-digital/", False, True)),
("liteiclink", ("http://github.com/enjoy-digital/", False, True)),
("litevideo", ("http://github.com/enjoy-digital/", False, True)),