From: Florent Kermarrec Date: Thu, 26 Feb 2015 08:35:14 +0000 (+0100) Subject: move files to liteeeth and create example_designs directory X-Git-Tag: 24jan2021_ls180~2602 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=60effe1d95b7140529010795c2eb9f7f565d289b;p=litex.git move files to liteeeth and create example_designs directory --- diff --git a/misoclib/LICENSE b/misoclib/LICENSE deleted file mode 100644 index cbbfe8be..00000000 --- a/misoclib/LICENSE +++ /dev/null @@ -1,28 +0,0 @@ -Unless otherwise noted, LiteEth is copyright (C) 2015 Florent Kermarrec. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -Other authors retain ownership of their contributions. If a submission can -reasonably be considered independently copyrightable, it's yours and we -encourage you to claim it with appropriate copyright notices. This submission -then falls under the "otherwise noted" category. All submissions are strongly -encouraged to use the two-clause BSD license reproduced above. diff --git a/misoclib/README b/misoclib/README deleted file mode 100644 index b3308328..00000000 --- a/misoclib/README +++ /dev/null @@ -1,142 +0,0 @@ - __ _ __ ______ __ - / / (_) /____ / __/ /_/ / - / /__/ / __/ -_) _// __/ _ \ - /____/_/\__/\__/___/\__/_//_/ - - Copyright 2012-2015 / EnjoyDigital - florent@enjoy-digital.fr - - A small footprint and configurable Ethernet core - with UDP/IP hw stack and Etherbone frontend - powered by Migen - -[> Doc ---------- -HTML : www.enjoy-digital.fr/litex/liteeth/ -PDF : www.enjoy-digital.fr/litex/liteeth.pdf - -[> Intro ---------- -LiteEth provides a small footprint and configurable Ethernet core. - -LiteEth is part of LiteX libraries whose aims are to lower entry level of -complex FPGA cores by providing simple, elegant and efficient implementations -ofcomponents used in today's SoC such as Ethernet, SATA, PCIe, SDRAM Controller... - -The core uses simple and specific streaming buses and will provides in the future -adapters to use standardized AXI or Avalon-ST streaming buses. - -Since Python is used to describe the HDL, the core is highly and easily -configurable. - -LiteEth uses technologies developed in partnership with M-Labs Ltd: - - Migen enables generating HDL with Python in an efficient way. - - MiSoC provides the basic blocks to build a powerful and small footprint SoC. - -LiteEth can be used as a Migen/MiSoC library (by simply installing it -with the provided setup.py) or can be integrated with your standard design flow -by generating the verilog rtl that you will use as a standard core. - -[> Features ------------ -- Ethernet MAC with various interfaces and various PHYs (GMII, MII, Loopback) -- Hardware UDP/IP stack with ARP and ICMP - -[> Possible improvements -------------------------- -- add standardized interfaces (AXI, Avalon-ST) -- add DMA interface to MAC -- add RGMII/SGMII PHYs -- ... See below Support and consulting :) - -If you want to support these features, please contact us at florent [AT] -enjoy-digital.fr. You can also contact our partner on the public mailing list -devel [AT] lists.m-labs.hk. - - -[> Getting started ------------------- -1. Install Python3 and your vendor's software - -2. Obtain Migen and install it: - git clone https://github.com/m-labs/migen - cd migen - python3 setup.py install - cd .. - -Note: in case you have issues with Migen, please retry -with our fork at: - https://github.com/enjoy-digital/misoc -until new features are merged. - -3. Obtain LiteScope and install it: - git clone https://github.com/enjoy-digital/litescope - cd litescope - python3 setup.py install - cd .. - -4. Obtain LiteEth - git clone https://github.com/enjoy-digital/liteeth - -5. Build and load UDP loopback design (only for KC705 for now): - python3 make.py -t udp all - -6. Test design (only for KC705 for now): - try to ping 192.168.1.40 - go to ./test directory: - change com port in config.py to your com port - run make test_udp - -7. Build and load Etherbone design (only for KC705 for now): - python3 make.py -t etherbone all - -8. Test design (only for KC705 for now): - try to ping 192.168.1.40 - go to ./test directory run: - run make test_etherbone - -[> Simulations: - Simulations are available in ./liteth/test/: - - mac_core_tb - - mac_wishbone_tb - - arp_tb - - ip_tb - - icmp_tb - - udp_tb - All ethernet layers have their own model tested against real Ethernet dumps (dumps.py) - To run a simulation, move to ./liteeth/test and run: - make simulation_name - -[> Tests : - An UDP loopback example is provided and be controlled with: ./test/test_udp.py - An Etherbone example with Wishbone SRAM is provided and can be controlled with: - ./test/test_etherbone.py - -[> License ------------ -LiteEth is released under the very permissive two-clause BSD license. Under -the terms of this license, you are authorized to use LiteEth for closed-source -proprietary designs. -Even though we do not require you to do so, those things are awesome, so please -do them if possible: - - tell us that you are using LiteEth - - cite LiteEth in publications related to research it has helped - - send us feedback and suggestions for improvements - - send us bug reports when something goes wrong - - send us the modifications and improvements you have done to LiteEth. - -[> Support and consulting --------------------------- -We love open-source hardware and like sharing our designs with others. - -LiteEth is developed and maintained by EnjoyDigital. - -If you would like to know more about LiteEth or if you are already a happy -user and would like to extend it for your needs, EnjoyDigital can provide standard -commercial support as well as consulting services. - -So feel free to contact us, we'd love to work with you! (and eventually shorten -the list of the possible improvements :) - -[> Contact -E-mail: florent [AT] enjoy-digital.fr \ No newline at end of file diff --git a/misoclib/liteeth-version.txt b/misoclib/liteeth-version.txt deleted file mode 100644 index eba33402..00000000 --- a/misoclib/liteeth-version.txt +++ /dev/null @@ -1,2 +0,0 @@ -0.9.0 - diff --git a/misoclib/liteeth/LICENSE b/misoclib/liteeth/LICENSE new file mode 100644 index 00000000..cbbfe8be --- /dev/null +++ b/misoclib/liteeth/LICENSE @@ -0,0 +1,28 @@ +Unless otherwise noted, LiteEth is copyright (C) 2015 Florent Kermarrec. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +Other authors retain ownership of their contributions. If a submission can +reasonably be considered independently copyrightable, it's yours and we +encourage you to claim it with appropriate copyright notices. This submission +then falls under the "otherwise noted" category. All submissions are strongly +encouraged to use the two-clause BSD license reproduced above. diff --git a/misoclib/liteeth/README b/misoclib/liteeth/README new file mode 100644 index 00000000..b3308328 --- /dev/null +++ b/misoclib/liteeth/README @@ -0,0 +1,142 @@ + __ _ __ ______ __ + / / (_) /____ / __/ /_/ / + / /__/ / __/ -_) _// __/ _ \ + /____/_/\__/\__/___/\__/_//_/ + + Copyright 2012-2015 / EnjoyDigital + florent@enjoy-digital.fr + + A small footprint and configurable Ethernet core + with UDP/IP hw stack and Etherbone frontend + powered by Migen + +[> Doc +--------- +HTML : www.enjoy-digital.fr/litex/liteeth/ +PDF : www.enjoy-digital.fr/litex/liteeth.pdf + +[> Intro +--------- +LiteEth provides a small footprint and configurable Ethernet core. + +LiteEth is part of LiteX libraries whose aims are to lower entry level of +complex FPGA cores by providing simple, elegant and efficient implementations +ofcomponents used in today's SoC such as Ethernet, SATA, PCIe, SDRAM Controller... + +The core uses simple and specific streaming buses and will provides in the future +adapters to use standardized AXI or Avalon-ST streaming buses. + +Since Python is used to describe the HDL, the core is highly and easily +configurable. + +LiteEth uses technologies developed in partnership with M-Labs Ltd: + - Migen enables generating HDL with Python in an efficient way. + - MiSoC provides the basic blocks to build a powerful and small footprint SoC. + +LiteEth can be used as a Migen/MiSoC library (by simply installing it +with the provided setup.py) or can be integrated with your standard design flow +by generating the verilog rtl that you will use as a standard core. + +[> Features +----------- +- Ethernet MAC with various interfaces and various PHYs (GMII, MII, Loopback) +- Hardware UDP/IP stack with ARP and ICMP + +[> Possible improvements +------------------------- +- add standardized interfaces (AXI, Avalon-ST) +- add DMA interface to MAC +- add RGMII/SGMII PHYs +- ... See below Support and consulting :) + +If you want to support these features, please contact us at florent [AT] +enjoy-digital.fr. You can also contact our partner on the public mailing list +devel [AT] lists.m-labs.hk. + + +[> Getting started +------------------ +1. Install Python3 and your vendor's software + +2. Obtain Migen and install it: + git clone https://github.com/m-labs/migen + cd migen + python3 setup.py install + cd .. + +Note: in case you have issues with Migen, please retry +with our fork at: + https://github.com/enjoy-digital/misoc +until new features are merged. + +3. Obtain LiteScope and install it: + git clone https://github.com/enjoy-digital/litescope + cd litescope + python3 setup.py install + cd .. + +4. Obtain LiteEth + git clone https://github.com/enjoy-digital/liteeth + +5. Build and load UDP loopback design (only for KC705 for now): + python3 make.py -t udp all + +6. Test design (only for KC705 for now): + try to ping 192.168.1.40 + go to ./test directory: + change com port in config.py to your com port + run make test_udp + +7. Build and load Etherbone design (only for KC705 for now): + python3 make.py -t etherbone all + +8. Test design (only for KC705 for now): + try to ping 192.168.1.40 + go to ./test directory run: + run make test_etherbone + +[> Simulations: + Simulations are available in ./liteth/test/: + - mac_core_tb + - mac_wishbone_tb + - arp_tb + - ip_tb + - icmp_tb + - udp_tb + All ethernet layers have their own model tested against real Ethernet dumps (dumps.py) + To run a simulation, move to ./liteeth/test and run: + make simulation_name + +[> Tests : + An UDP loopback example is provided and be controlled with: ./test/test_udp.py + An Etherbone example with Wishbone SRAM is provided and can be controlled with: + ./test/test_etherbone.py + +[> License +----------- +LiteEth is released under the very permissive two-clause BSD license. Under +the terms of this license, you are authorized to use LiteEth for closed-source +proprietary designs. +Even though we do not require you to do so, those things are awesome, so please +do them if possible: + - tell us that you are using LiteEth + - cite LiteEth in publications related to research it has helped + - send us feedback and suggestions for improvements + - send us bug reports when something goes wrong + - send us the modifications and improvements you have done to LiteEth. + +[> Support and consulting +-------------------------- +We love open-source hardware and like sharing our designs with others. + +LiteEth is developed and maintained by EnjoyDigital. + +If you would like to know more about LiteEth or if you are already a happy +user and would like to extend it for your needs, EnjoyDigital can provide standard +commercial support as well as consulting services. + +So feel free to contact us, we'd love to work with you! (and eventually shorten +the list of the possible improvements :) + +[> Contact +E-mail: florent [AT] enjoy-digital.fr \ No newline at end of file diff --git a/misoclib/liteeth/example_designs/make.py b/misoclib/liteeth/example_designs/make.py new file mode 100644 index 00000000..c55c8339 --- /dev/null +++ b/misoclib/liteeth/example_designs/make.py @@ -0,0 +1,141 @@ +#!/usr/bin/env python3 + +import sys, os, argparse, subprocess, struct, importlib + +from mibuild.tools import write_to_file +from migen.util.misc import autotype +from migen.fhdl import verilog, edif +from migen.fhdl.structure import _Fragment +from migen.bank.description import CSRStatus +from mibuild import tools +from mibuild.xilinx_common import * + +from liteeth.common import * + +def get_csr_csv(regions): + r = "" + for name, origin, busword, obj in regions: + if not isinstance(obj, Memory): + for csr in obj: + nr = (csr.size + busword - 1)//busword + r += "{}_{},0x{:08x},{},{}\n".format(name, csr.name, origin, nr, "ro" if isinstance(csr, CSRStatus) else "rw") + origin += 4*nr + return r + +def _import(default, name): + return importlib.import_module(default + "." + name) + +def _get_args(): + parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter, + description="""\ +LiteEth - based on Migen. + +This program builds and/or loads LiteEth components. +One or several actions can be specified: + +clean delete previous build(s). +build-rtl build verilog rtl. +build-bitstream build-bitstream build FPGA bitstream. +build-csr-csv save CSR map into CSV file. + +load-bitstream load bitstream into volatile storage. + +all clean, build-csr-csv, build-bitstream, load-bitstream. +""") + + parser.add_argument("-t", "--target", default="base", help="Core type to build") + parser.add_argument("-s", "--sub-target", default="", help="variant of the Core type to build") + parser.add_argument("-p", "--platform", default=None, help="platform to build for") + parser.add_argument("-Ot", "--target-option", default=[], nargs=2, action="append", help="set target-specific option") + parser.add_argument("-Op", "--platform-option", default=[("programmer", "vivado")], nargs=2, action="append", help="set platform-specific option") + parser.add_argument("--csr_csv", default="./test/csr.csv", help="CSV file to save the CSR map into") + + parser.add_argument("action", nargs="+", help="specify an action") + + return parser.parse_args() + +# Note: misoclib need to be installed as a python library + +if __name__ == "__main__": + args = _get_args() + + # create top-level Core object + target_module = _import("targets", args.target) + if args.sub_target: + top_class = getattr(target_module, args.sub_target) + else: + top_class = target_module.default_subtarget + + if args.platform is None: + platform_name = top_class.default_platform + else: + platform_name = args.platform + platform_module = _import("platforms", platform_name) + platform_kwargs = dict((k, autotype(v)) for k, v in args.platform_option) + platform = platform_module.Platform(**platform_kwargs) + + build_name = top_class.__name__.lower() + "-" + platform_name + top_kwargs = dict((k, autotype(v)) for k, v in args.target_option) + soc = top_class(platform, **top_kwargs) + soc.finalize() + + # decode actions + action_list = ["clean", "build-csr-csv", "build-bitstream", "load-bitstream", "all"] + actions = {k: False for k in action_list} + for action in args.action: + if action in actions: + actions[action] = True + else: + print("Unknown action: "+action+". Valid actions are:") + for a in action_list: + print(" "+a) + sys.exit(1) + + print(""" + __ _ __ ______ __ + / / (_) /____ / __/ /_/ / + / /__/ / __/ -_) _// __/ _ \\ + /____/_/\__/\__/___/\__/_//_/ + + A small footprint and configurable Ethernet + core powered by Migen +====== Building options: ====== +Platform: {} +Target: {} +Subtarget: {} +System Clk: {} MHz +===============================""".format( + platform_name, + args.target, + top_class.__name__, + soc.clk_freq/1000000 + ) +) + + # dependencies + if actions["all"]: + actions["build-csr-csv"] = True + actions["build-bitstream"] = True + actions["load-bitstream"] = True + + if actions["build-bitstream"]: + actions["build-csr-csv"] = True + actions["build-bitstream"] = True + actions["load-bitstream"] = True + + if actions["clean"]: + subprocess.call(["rm", "-rf", "build/*"]) + + if actions["build-csr-csv"]: + csr_csv = get_csr_csv(soc.cpu_csr_regions) + write_to_file(args.csr_csv, csr_csv) + + if actions["build-bitstream"]: + vns = platform.build(soc, build_name=build_name) + if hasattr(soc, "do_exit") and vns is not None: + if hasattr(soc.do_exit, '__call__'): + soc.do_exit(vns) + + if actions["load-bitstream"]: + prog = platform.create_programmer() + prog.load_bitstream("build/" + build_name + platform.bitstream_ext) diff --git a/misoclib/liteeth/example_designs/platforms/kc705.py b/misoclib/liteeth/example_designs/platforms/kc705.py new file mode 100644 index 00000000..500d1b07 --- /dev/null +++ b/misoclib/liteeth/example_designs/platforms/kc705.py @@ -0,0 +1,138 @@ +from mibuild.generic_platform import * +from mibuild.crg import SimpleCRG +from mibuild.xilinx_common import CRG_DS +from mibuild.xilinx_ise import XilinxISEPlatform +from mibuild.xilinx_vivado import XilinxVivadoPlatform +from mibuild.programmer import * + +def _run_vivado(cmds): + with subprocess.Popen("vivado -mode tcl", stdin=subprocess.PIPE, shell=True) as process: + process.stdin.write(cmds.encode("ASCII")) + process.communicate() + +class VivadoProgrammer(Programmer): + needs_bitreverse = False + + def load_bitstream(self, bitstream_file): + cmds = """open_hw +connect_hw_server +open_hw_target [lindex [get_hw_targets -of_objects [get_hw_servers localhost]] 0] + +set_property PROBES.FILE {{}} [lindex [get_hw_devices] 0] +set_property PROGRAM.FILE {{{bitstream}}} [lindex [get_hw_devices] 0] + +program_hw_devices [lindex [get_hw_devices] 0] +refresh_hw_device [lindex [get_hw_devices] 0] + +quit +""".format(bitstream=bitstream_file) + _run_vivado(cmds) + + def flash(self, address, data_file): + raise NotImplementedError + +_io = [ + ("user_led", 0, Pins("AB8"), IOStandard("LVCMOS15")), + ("user_led", 1, Pins("AA8"), IOStandard("LVCMOS15")), + ("user_led", 2, Pins("AC9"), IOStandard("LVCMOS15")), + ("user_led", 3, Pins("AB9"), IOStandard("LVCMOS15")), + ("user_led", 4, Pins("AE26"), IOStandard("LVCMOS25")), + ("user_led", 5, Pins("G19"), IOStandard("LVCMOS25")), + ("user_led", 6, Pins("E18"), IOStandard("LVCMOS25")), + ("user_led", 7, Pins("F16"), IOStandard("LVCMOS25")), + + ("cpu_reset", 0, Pins("AB7"), IOStandard("LVCMOS15")), + + ("clk200", 0, + Subsignal("p", Pins("AD12"), IOStandard("LVDS")), + Subsignal("n", Pins("AD11"), IOStandard("LVDS")) + ), + + ("clk156", 0, + Subsignal("p", Pins("K28"), IOStandard("LVDS_25")), + Subsignal("n", Pins("K29"), IOStandard("LVDS_25")) + ), + + + ("serial", 0, + Subsignal("cts", Pins("L27")), + Subsignal("rts", Pins("K23")), + Subsignal("tx", Pins("K24")), + Subsignal("rx", Pins("M19")), + IOStandard("LVCMOS25") + ), + + ("eth_clocks", 0, + Subsignal("tx", Pins("M28")), + Subsignal("gtx", Pins("K30")), + Subsignal("rx", Pins("U27")), + IOStandard("LVCMOS25") + ), + ("eth", 0, + Subsignal("rst_n", Pins("L20")), + Subsignal("int_n", Pins("N30")), + Subsignal("mdio", Pins("J21")), + Subsignal("mdc", Pins("R23")), + Subsignal("dv", Pins("R28")), + Subsignal("rx_er", Pins("V26")), + Subsignal("rx_data", Pins("U30 U25 T25 U28 R19 T27 T26 T28")), + Subsignal("tx_en", Pins("M27")), + Subsignal("tx_er", Pins("N29")), + Subsignal("tx_data", Pins("N27 N25 M29 L28 J26 K26 L30 J28")), + Subsignal("col", Pins("W19")), + Subsignal("crs", Pins("R30")), + IOStandard("LVCMOS25") + ), + +] + +def Platform(*args, toolchain="vivado", programmer="xc3sprog", **kwargs): + if toolchain == "ise": + xilinx_platform = XilinxISEPlatform + elif toolchain == "vivado": + xilinx_platform = XilinxVivadoPlatform + else: + raise ValueError + + class RealPlatform(xilinx_platform): + bitgen_opt = "-g LCK_cycle:6 -g Binary:Yes -w -g ConfigRate:12 -g SPI_buswidth:4" + + def __init__(self, crg_factory=lambda p: CRG_DS(p, "clk200", "cpu_reset")): + xilinx_platform.__init__(self, "xc7k325t-ffg900-2", _io, crg_factory) + + def create_programmer(self): + if programmer == "xc3sprog": + return XC3SProg("jtaghs1_fast", "bscan_spi_kc705.bit") + elif programmer == "vivado": + return VivadoProgrammer() + else: + raise ValueError + + def do_finalize(self, fragment): + try: + self.add_period_constraint(self.lookup_request("clk156").p, 6.4) + except ConstraintError: + pass + try: + self.add_period_constraint(self.lookup_request("clk200").p, 5.0) + except ConstraintError: + pass + try: + self.add_period_constraint(self.lookup_request("eth_clocks").rx, 8.0) + except ConstraintError: + pass + self.add_platform_command(""" +create_clock -name sys_clk -period 6 [get_nets sys_clk] +create_clock -name eth_rx_clk -period 8 [get_nets eth_rx_clk] +create_clock -name eth_tx_clk -period 8 [get_nets eth_tx_clk] + +set_false_path -from [get_clocks sys_clk] -to [get_clocks eth_rx_clk] +set_false_path -from [get_clocks sys_clk] -to [get_clocks eth_tx_clk] +set_false_path -from [get_clocks eth_rx_clk] -to [get_clocks sys_clk] +set_false_path -from [get_clocks eth_tx_clk] -to [get_clocks sys_clk] + +set_property CFGBVS VCCO [current_design] +set_property CONFIG_VOLTAGE 2.5 [current_design] +""") + + return RealPlatform(*args, **kwargs) diff --git a/misoclib/liteeth/example_designs/targets/__init__.py b/misoclib/liteeth/example_designs/targets/__init__.py new file mode 100644 index 00000000..85efe5d9 --- /dev/null +++ b/misoclib/liteeth/example_designs/targets/__init__.py @@ -0,0 +1,26 @@ +import subprocess + +from migen.fhdl.std import * +from migen.bank.description import * + +def get_id(): + output = subprocess.check_output(["git", "rev-parse", "HEAD"]).decode("ascii") + return int(output[:8], 16) + +class Identifier(Module, AutoCSR): + def __init__(self, sysid, frequency, revision=None): + self._r_sysid = CSRStatus(16) + self._r_revision = CSRStatus(32) + self._r_frequency = CSRStatus(32) + + ### + + if revision is None: + revision = get_id() + + self.comb += [ + self._r_sysid.status.eq(sysid), + self._r_revision.status.eq(revision), + self._r_frequency.status.eq(frequency), + ] + diff --git a/misoclib/liteeth/example_designs/targets/base.py b/misoclib/liteeth/example_designs/targets/base.py new file mode 100644 index 00000000..3fe1f2a4 --- /dev/null +++ b/misoclib/liteeth/example_designs/targets/base.py @@ -0,0 +1,224 @@ +import os + +from migen.bank import csrgen +from migen.bus import wishbone, csr +from migen.bus import wishbone2csr +from migen.genlib.cdc import * +from migen.genlib.resetsync import AsyncResetSynchronizer +from migen.bank.description import * + +from targets import * + +from litescope.common import * +from litescope.bridge.uart2wb import LiteScopeUART2WB +from litescope.frontend.la import LiteScopeLA +from litescope.core.port import LiteScopeTerm + +from liteeth.common import * +from liteeth.generic import * +from liteeth.phy.gmii import LiteEthPHYGMII +from liteeth.core import LiteEthUDPIPCore + +class _CRG(Module): + def __init__(self, platform): + self.clock_domains.cd_sys = ClockDomain() + self.reset = Signal() + + clk200 = platform.request("clk200") + clk200_se = Signal() + self.specials += Instance("IBUFDS", i_I=clk200.p, i_IB=clk200.n, o_O=clk200_se) + + pll_locked = Signal() + pll_fb = Signal() + pll_sys = Signal() + self.specials += [ + Instance("PLLE2_BASE", + p_STARTUP_WAIT="FALSE", o_LOCKED=pll_locked, + + # VCO @ 1GHz + p_REF_JITTER1=0.01, p_CLKIN1_PERIOD=5.0, + p_CLKFBOUT_MULT=5, p_DIVCLK_DIVIDE=1, + i_CLKIN1=clk200_se, i_CLKFBIN=pll_fb, o_CLKFBOUT=pll_fb, + + # 166MHz + p_CLKOUT0_DIVIDE=6, p_CLKOUT0_PHASE=0.0, o_CLKOUT0=pll_sys, + + p_CLKOUT1_DIVIDE=2, p_CLKOUT1_PHASE=0.0, #o_CLKOUT1=, + + p_CLKOUT2_DIVIDE=2, p_CLKOUT2_PHASE=0.0, #o_CLKOUT2=, + + p_CLKOUT3_DIVIDE=2, p_CLKOUT3_PHASE=0.0, #o_CLKOUT3=, + + p_CLKOUT4_DIVIDE=2, p_CLKOUT4_PHASE=0.0, #o_CLKOUT4= + ), + Instance("BUFG", i_I=pll_sys, o_O=self.cd_sys.clk), + AsyncResetSynchronizer(self.cd_sys, ~pll_locked | platform.request("cpu_reset") | self.reset), + ] + +class GenSoC(Module): + csr_base = 0x00000000 + csr_data_width = 32 + csr_map = { + "bridge": 0, + "identifier": 1, + } + interrupt_map = {} + cpu_type = None + def __init__(self, platform, clk_freq): + self.clk_freq = clk_freq + # UART <--> Wishbone bridge + self.submodules.bridge = LiteScopeUART2WB(platform.request("serial"), clk_freq, baud=921600) + + # CSR bridge 0x00000000 (shadow @0x00000000) + self.submodules.wishbone2csr = wishbone2csr.WB2CSR(bus_csr=csr.Interface(self.csr_data_width)) + self._wb_masters = [self.bridge.wishbone] + self._wb_slaves = [(lambda a: a[23:25] == 0, self.wishbone2csr.wishbone)] + self.cpu_csr_regions = [] # list of (name, origin, busword, csr_list/Memory) + + # CSR + self.submodules.identifier = Identifier(0, int(clk_freq), 0) + + def add_wb_master(self, wbm): + if self.finalized: + raise FinalizeError + self._wb_masters.append(wbm) + + def add_wb_slave(self, address_decoder, interface): + if self.finalized: + raise FinalizeError + self._wb_slaves.append((address_decoder, interface)) + + def add_cpu_memory_region(self, name, origin, length): + self.cpu_memory_regions.append((name, origin, length)) + + def add_cpu_csr_region(self, name, origin, busword, obj): + self.cpu_csr_regions.append((name, origin, busword, obj)) + + def do_finalize(self): + # Wishbone + self.submodules.wishbonecon = wishbone.InterconnectShared(self._wb_masters, + self._wb_slaves, register=True) + + # CSR + self.submodules.csrbankarray = csrgen.BankArray(self, + lambda name, memory: self.csr_map[name if memory is None else name + "_" + memory.name_override], + data_width=self.csr_data_width) + self.submodules.csrcon = csr.Interconnect(self.wishbone2csr.csr, self.csrbankarray.get_buses()) + for name, csrs, mapaddr, rmap in self.csrbankarray.banks: + self.add_cpu_csr_region(name, 0xe0000000+0x800*mapaddr, flen(rmap.bus.dat_w), csrs) + for name, memory, mapaddr, mmap in self.csrbankarray.srams: + self.add_cpu_csr_region(name, 0xe0000000+0x800*mapaddr, flen(rmap.bus.dat_w), memory) + +class BaseSoC(GenSoC, AutoCSR): + default_platform = "kc705" + csr_map = { + "phy": 11, + "core": 12 + } + csr_map.update(GenSoC.csr_map) + def __init__(self, platform, clk_freq=166*1000000, + mac_address=0x10e2d5000000, + ip_address="192.168.1.40"): + GenSoC.__init__(self, platform, clk_freq) + self.submodules.crg = _CRG(platform) + + # wishbone SRAM (to test Wishbone over UART and Etherbone) + self.submodules.sram = wishbone.SRAM(1024) + self.add_wb_slave(lambda a: a[23:25] == 1, self.sram.bus) + + # ethernet PHY and UDP/IP stack + self.submodules.phy = LiteEthPHYGMII(platform.request("eth_clocks"), platform.request("eth")) + self.submodules.core = LiteEthUDPIPCore(self.phy, mac_address, convert_ip(ip_address), clk_freq) + +class BaseSoCDevel(BaseSoC, AutoCSR): + csr_map = { + "la": 20 + } + csr_map.update(BaseSoC.csr_map) + def __init__(self, platform): + BaseSoC.__init__(self, platform) + + self.core_icmp_rx_fsm_state = Signal(4) + self.core_icmp_tx_fsm_state = Signal(4) + self.core_udp_rx_fsm_state = Signal(4) + self.core_udp_tx_fsm_state = Signal(4) + self.core_ip_rx_fsm_state = Signal(4) + self.core_ip_tx_fsm_state = Signal(4) + self.core_arp_rx_fsm_state = Signal(4) + self.core_arp_tx_fsm_state = Signal(4) + self.core_arp_table_fsm_state = Signal(4) + + debug = ( + # MAC interface + self.core.mac.core.sink.stb, + self.core.mac.core.sink.sop, + self.core.mac.core.sink.eop, + self.core.mac.core.sink.ack, + self.core.mac.core.sink.data, + + self.core.mac.core.source.stb, + self.core.mac.core.source.sop, + self.core.mac.core.source.eop, + self.core.mac.core.source.ack, + self.core.mac.core.source.data, + + # ICMP interface + self.core.icmp.echo.sink.stb, + self.core.icmp.echo.sink.sop, + self.core.icmp.echo.sink.eop, + self.core.icmp.echo.sink.ack, + self.core.icmp.echo.sink.data, + + self.core.icmp.echo.source.stb, + self.core.icmp.echo.source.sop, + self.core.icmp.echo.source.eop, + self.core.icmp.echo.source.ack, + self.core.icmp.echo.source.data, + + # IP interface + self.core.ip.crossbar.master.sink.stb, + self.core.ip.crossbar.master.sink.sop, + self.core.ip.crossbar.master.sink.eop, + self.core.ip.crossbar.master.sink.ack, + self.core.ip.crossbar.master.sink.data, + self.core.ip.crossbar.master.sink.ip_address, + self.core.ip.crossbar.master.sink.protocol, + + # State machines + self.core_icmp_rx_fsm_state, + self.core_icmp_tx_fsm_state, + + self.core_arp_rx_fsm_state, + self.core_arp_tx_fsm_state, + self.core_arp_table_fsm_state, + + self.core_ip_rx_fsm_state, + self.core_ip_tx_fsm_state, + + self.core_udp_rx_fsm_state, + self.core_udp_tx_fsm_state + ) + self.submodules.la = LiteScopeLA(debug, 4096) + self.la.trigger.add_port(LiteScopeTerm(self.la.dw)) + + def do_finalize(self): + BaseSoC.do_finalize(self) + self.comb += [ + self.core_icmp_rx_fsm_state.eq(self.core.icmp.rx.fsm.state), + self.core_icmp_tx_fsm_state.eq(self.core.icmp.tx.fsm.state), + + self.core_arp_rx_fsm_state.eq(self.core.arp.rx.fsm.state), + self.core_arp_tx_fsm_state.eq(self.core.arp.tx.fsm.state), + self.core_arp_table_fsm_state.eq(self.core.arp.table.fsm.state), + + self.core_ip_rx_fsm_state.eq(self.core.ip.rx.fsm.state), + self.core_ip_tx_fsm_state.eq(self.core.ip.tx.fsm.state), + + self.core_udp_rx_fsm_state.eq(self.core.udp.rx.fsm.state), + self.core_udp_tx_fsm_state.eq(self.core.udp.tx.fsm.state) + ] + + def do_exit(self, vns): + self.la.export(vns, "test/la.csv") + +default_subtarget = BaseSoC diff --git a/misoclib/liteeth/example_designs/targets/etherbone.py b/misoclib/liteeth/example_designs/targets/etherbone.py new file mode 100644 index 00000000..0aaaf2d2 --- /dev/null +++ b/misoclib/liteeth/example_designs/targets/etherbone.py @@ -0,0 +1,71 @@ +from litescope.common import * +from litescope.frontend.la import LiteScopeLA +from litescope.core.port import LiteScopeTerm + +from liteeth.common import * +from liteeth.generic import * + +from targets.base import BaseSoC +from liteeth.core.etherbone import LiteEthEtherbone + +class EtherboneSoC(BaseSoC): + default_platform = "kc705" + def __init__(self, platform): + BaseSoC.__init__(self, platform, + mac_address=0x10e2d5000000, + ip_address="192.168.1.40") + self.submodules.etherbone = LiteEthEtherbone(self.core.udp, 20000) + self.add_wb_master(self.etherbone.master.bus) + +class EtherboneSoCDevel(EtherboneSoC): + csr_map = { + "la": 20 + } + csr_map.update(EtherboneSoC.csr_map) + def __init__(self, platform): + EtherboneSoC.__init__(self, platform) + debug = ( + # mmap stream from HOST + self.etherbone.master.sink.stb, + self.etherbone.master.sink.sop, + self.etherbone.master.sink.eop, + self.etherbone.master.sink.ack, + self.etherbone.master.sink.we, + self.etherbone.master.sink.count, + self.etherbone.master.sink.base_addr, + self.etherbone.master.sink.be, + self.etherbone.master.sink.addr, + self.etherbone.master.sink.data, + + # mmap stream to HOST + self.etherbone.master.source.stb, + self.etherbone.master.source.sop, + self.etherbone.master.source.eop, + self.etherbone.master.source.ack, + self.etherbone.master.source.we, + self.etherbone.master.source.count, + self.etherbone.master.source.base_addr, + self.etherbone.master.source.be, + self.etherbone.master.source.addr, + self.etherbone.master.source.data, + + # etherbone wishbone master + self.etherbone.master.bus.dat_w, + self.etherbone.master.bus.dat_r, + self.etherbone.master.bus.adr, + self.etherbone.master.bus.sel, + self.etherbone.master.bus.cyc, + self.etherbone.master.bus.stb, + self.etherbone.master.bus.ack, + self.etherbone.master.bus.we, + self.etherbone.master.bus.cti, + self.etherbone.master.bus.bte, + self.etherbone.master.bus.err + ) + self.submodules.la = LiteScopeLA(debug, 4096) + self.la.trigger.add_port(LiteScopeTerm(self.la.dw)) + + def do_exit(self, vns): + self.la.export(vns, "test/la.csv") + +default_subtarget = EtherboneSoC diff --git a/misoclib/liteeth/example_designs/targets/tty.py b/misoclib/liteeth/example_designs/targets/tty.py new file mode 100644 index 00000000..28cda9d8 --- /dev/null +++ b/misoclib/liteeth/example_designs/targets/tty.py @@ -0,0 +1,42 @@ +from litescope.common import * +from litescope.frontend.la import LiteScopeLA +from litescope.core.port import LiteScopeTerm + +from liteeth.common import * +from liteeth.generic import * + +from targets.base import BaseSoC +from liteeth.core.tty import LiteEthTTY + +class TTYSoC(BaseSoC): + default_platform = "kc705" + def __init__(self, platform): + BaseSoC.__init__(self, platform, + mac_address=0x10e2d5000000, + ip_address="192.168.1.40") + self.submodules.tty = LiteEthTTY(self.core.udp, convert_ip("192.168.1.12"), 10000) + self.comb += Record.connect(self.tty.source, self.tty.sink) + +class TTYSoCDevel(TTYSoC): + csr_map = { + "la": 20 + } + csr_map.update(TTYSoC.csr_map) + def __init__(self, platform): + TTYSoC.__init__(self, platform) + debug = ( + self.tty.sink.stb, + self.tty.sink.ack, + self.tty.sink.data, + + self.tty.source.stb, + self.tty.source.ack, + self.tty.source.data + ) + self.submodules.la = LiteScopeLA(debug, 4096) + self.la.trigger.add_port(LiteScopeTerm(self.la.dw)) + + def do_exit(self, vns): + self.la.export(vns, "test/la.csv") + +default_subtarget = TTYSoC diff --git a/misoclib/liteeth/example_designs/targets/udp.py b/misoclib/liteeth/example_designs/targets/udp.py new file mode 100644 index 00000000..9ce15ce5 --- /dev/null +++ b/misoclib/liteeth/example_designs/targets/udp.py @@ -0,0 +1,69 @@ +from litescope.common import * +from litescope.frontend.la import LiteScopeLA +from litescope.core.port import LiteScopeTerm + +from liteeth.common import * +from liteeth.generic import * + +from targets.base import BaseSoC + +class UDPSoC(BaseSoC): + default_platform = "kc705" + def __init__(self, platform): + BaseSoC.__init__(self, platform, + mac_address=0x10e2d5000000, + ip_address="192.168.1.40") + + # add udp loopback on port 6000 with dw=8 + self.add_udp_loopback(6000, 8, 8192, "loopback_8") + # add udp loopback on port 8000 with dw=32 + self.add_udp_loopback(8000, 32, 8192, "loopback_32") + + def add_udp_loopback(self, port, dw, depth, name=None): + port = self.core.udp.crossbar.get_port(port, dw) + buf = PacketBuffer(eth_udp_user_description(dw), depth//(dw//8), 8) + if name is None: + self.submodules += buf + else: + setattr(self.submodules, name, buf) + self.comb += Port.connect(port, buf) + +class UDPSoCDevel(UDPSoC): + csr_map = { + "la": 20 + } + csr_map.update(UDPSoC.csr_map) + def __init__(self, platform): + UDPSoC.__init__(self, platform) + debug = ( + self.loopback_8.sink.stb, + self.loopback_8.sink.sop, + self.loopback_8.sink.eop, + self.loopback_8.sink.ack, + self.loopback_8.sink.data, + + self.loopback_8.source.stb, + self.loopback_8.source.sop, + self.loopback_8.source.eop, + self.loopback_8.source.ack, + self.loopback_8.source.data, + + self.loopback_32.sink.stb, + self.loopback_32.sink.sop, + self.loopback_32.sink.eop, + self.loopback_32.sink.ack, + self.loopback_32.sink.data, + + self.loopback_32.source.stb, + self.loopback_32.source.sop, + self.loopback_32.source.eop, + self.loopback_32.source.ack, + self.loopback_32.source.data + ) + self.submodules.la = LiteScopeLA(debug, 4096) + self.la.trigger.add_port(LiteScopeTerm(self.la.dw)) + + def do_exit(self, vns): + self.la.export(vns, "test/la.csv") + +default_subtarget = UDPSoC diff --git a/misoclib/liteeth/example_designs/test/make.py b/misoclib/liteeth/example_designs/test/make.py new file mode 100644 index 00000000..05e13aad --- /dev/null +++ b/misoclib/liteeth/example_designs/test/make.py @@ -0,0 +1,33 @@ +#!/usr/bin/env python3 +import argparse, importlib + +def _get_args(): + parser = argparse.ArgumentParser() + parser.add_argument("-b", "--bridge", default="uart", help="Bridge to use") + parser.add_argument("--port", default=2, help="UART port") + parser.add_argument("--baudrate", default=921600, help="UART baudrate") + parser.add_argument("--ip_address", default="192.168.1.40", help="Etherbone IP address") + parser.add_argument("--udp_port", default=20000, help="Etherbone UDP port") + parser.add_argument("--busword", default=32, help="CSR busword") + + parser.add_argument("test", nargs="+", help="specify a test") + + return parser.parse_args() + +if __name__ == "__main__": + args = _get_args() + if args.bridge == "uart": + from litescope.host.driver.uart import LiteScopeUARTDriver + wb = LiteScopeUARTDriver(args.port, args.baudrate, "./csr.csv", int(args.busword), debug=False) + elif args.bridge == "etherbone": + from litescope.host.driver.etherbone import LiteScopeEtherboneDriver + wb = LiteScopeEtherboneDriver(args.ip_address, int(args.udp_port), "./csr.csv", int(args.busword), debug=False) + else: + ValueError("Invalid bridge {}".format(args.bridge)) + + def _import(name): + return importlib.import_module(name) + + for test in args.test: + t = _import("test_"+test) + t.main(wb) diff --git a/misoclib/liteeth/example_designs/test/test_etherbone.py b/misoclib/liteeth/example_designs/test/test_etherbone.py new file mode 100644 index 00000000..4622d524 --- /dev/null +++ b/misoclib/liteeth/example_designs/test/test_etherbone.py @@ -0,0 +1,60 @@ +import socket, time +from liteeth.test.model.etherbone import * + +SRAM_BASE = 0x02000000 + +import socket + +def main(wb): + sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + + # test probe + packet = EtherbonePacket() + packet.pf = 1 + packet.encode() + sock.sendto(bytes(packet), ("192.168.1.40", 20000)) + time.sleep(0.01) + + # test writes + writes_datas = [j for j in range(16)] + writes = EtherboneWrites(base_addr=SRAM_BASE, datas=writes_datas) + record = EtherboneRecord() + record.writes = writes + record.reads = None + record.bca = 0 + record.rca = 0 + record.rff = 0 + record.cyc = 0 + record.wca = 0 + record.wff = 0 + record.byte_enable = 0xf + record.wcount = len(writes_datas) + record.rcount = 0 + + packet = EtherbonePacket() + packet.records = [record] + packet.encode() + sock.sendto(bytes(packet), ("192.168.1.40", 20000)) + time.sleep(0.01) + + # test reads + reads_addrs = [SRAM_BASE+4*j for j in range(16)] + reads = EtherboneReads(base_ret_addr=0x1000, addrs=reads_addrs) + record = EtherboneRecord() + record.writes = None + record.reads = reads + record.bca = 0 + record.rca = 0 + record.rff = 0 + record.cyc = 0 + record.wca = 0 + record.wff = 0 + record.byte_enable = 0xf + record.wcount = 0 + record.rcount = len(reads_addrs) + + packet = EtherbonePacket() + packet.records = [record] + packet.encode() + sock.sendto(bytes(packet), ("192.168.1.40", 20000)) + time.sleep(0.01) diff --git a/misoclib/liteeth/example_designs/test/test_la.py b/misoclib/liteeth/example_designs/test/test_la.py new file mode 100644 index 00000000..c15de8c8 --- /dev/null +++ b/misoclib/liteeth/example_designs/test/test_la.py @@ -0,0 +1,24 @@ +import time +from litescope.host.driver.la import LiteScopeLADriver + +def main(wb): + la = LiteScopeLADriver(wb.regs, "la", debug=True) + + wb.open() + regs = wb.regs + ### + + conditions = {} + la.configure_term(port=0, cond=conditions) + la.configure_sum("term") + # Run Logic Analyzer + la.run(offset=2048, length=4000) + + while not la.done(): + pass + + la.upload() + la.save("dump.vcd") + + ### + wb.close() diff --git a/misoclib/liteeth/example_designs/test/test_regs.py b/misoclib/liteeth/example_designs/test/test_regs.py new file mode 100644 index 00000000..f2685cf5 --- /dev/null +++ b/misoclib/liteeth/example_designs/test/test_regs.py @@ -0,0 +1,12 @@ +def main(wb): + wb.open() + regs = wb.regs + ### + print("sysid : 0x%04x" %regs.identifier_sysid.read()) + print("revision : 0x%04x" %regs.identifier_revision.read()) + print("frequency : %d MHz" %(regs.identifier_frequency.read()/1000000)) + SRAM_BASE = 0x02000000 + wb.write(SRAM_BASE, [i for i in range(64)]) + print(wb.read(SRAM_BASE, 64)) + ### + wb.close() diff --git a/misoclib/liteeth/example_designs/test/test_tty.py b/misoclib/liteeth/example_designs/test/test_tty.py new file mode 100644 index 00000000..af6f2df0 --- /dev/null +++ b/misoclib/liteeth/example_designs/test/test_tty.py @@ -0,0 +1,36 @@ +import socket +import threading + +def test(fpga_ip, udp_port, test_message): + tx_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + rx_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + rx_sock.bind(("", udp_port)) + rx_sock.settimeout(0.5) + + def receive(): + while True: + try: + msg = rx_sock.recv(8192) + for byte in msg: + print(chr(byte), end="") + except: + break + + def send(): + tx_sock.sendto(bytes(test_message, "utf-8"), (fpga_ip, udp_port)) + + receive_thread = threading.Thread(target=receive) + receive_thread.start() + + send_thread = threading.Thread(target=send) + send_thread.start() + + try: + send_thread.join(5) + send_thread.join(5) + except KeyboardInterrupt: + pass + +def main(wb): + test_message = "LiteEth virtual TTY Hello world\n" + test("192.168.1.40", 10000, test_message) diff --git a/misoclib/liteeth/example_designs/test/test_udp.py b/misoclib/liteeth/example_designs/test/test_udp.py new file mode 100644 index 00000000..65d47b74 --- /dev/null +++ b/misoclib/liteeth/example_designs/test/test_udp.py @@ -0,0 +1,81 @@ +import socket +import time +import threading +import copy + +KB = 1024 +MB = 1024*KB +GB = 1024*MB + +def seed_to_data(seed, random=True): + if random: + return (seed * 0x31415979 + 1) & 0xffffffff + else: + return seed + +def check(p1, p2): + p1 = copy.deepcopy(p1) + p2 = copy.deepcopy(p2) + if isinstance(p1, int): + return 0, 1, int(p1 != p2) + else: + if len(p1) >= len(p2): + ref, res = p1, p2 + else: + ref, res = p2, p1 + shift = 0 + while((ref[0] != res[0]) and (len(res)>1)): + res.pop(0) + shift += 1 + length = min(len(ref), len(res)) + errors = 0 + for i in range(length): + if ref.pop(0) != res.pop(0): + errors += 1 + return shift, length, errors + +def generate_packet(seed, length): + r = [] + for i in range(length): + r.append(seed_to_data(seed, True)%0xff) # XXX FIXME + seed += 1 + return r, seed + +def test(fpga_ip, udp_port, test_size): + tx_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + rx_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + rx_sock.bind(("", udp_port)) + + def receive(): + rx_seed = 0 + while rx_seed < test_size: + data, addr = rx_sock.recvfrom(8192) + rx_packet = [] + for byte in data: + rx_packet.append(int(byte)) + rx_reference_packet, rx_seed = generate_packet(rx_seed, 1024) + s, l, e = check(rx_reference_packet, rx_packet) + print("shift "+ str(s) + " / length " + str(l) + " / errors " + str(e)) + + def send(): + tx_seed = 0 + while tx_seed < test_size: + tx_packet, tx_seed = generate_packet(tx_seed, 1024) + tx_sock.sendto(bytes(tx_packet), (fpga_ip, udp_port)) + time.sleep(0.001) # XXX: FIXME, Python limitation? + + receive_thread = threading.Thread(target=receive) + receive_thread.start() + + send_thread = threading.Thread(target=send) + send_thread.start() + + try: + send_thread.join(10) + receive_thread.join(0.1) + except KeyboardInterrupt: + pass + +def main(wb): + test("192.168.1.40", 6000, 128*KB) + test("192.168.1.40", 8000, 128*KB) diff --git a/misoclib/liteeth/liteeth-version.txt b/misoclib/liteeth/liteeth-version.txt new file mode 100644 index 00000000..eba33402 --- /dev/null +++ b/misoclib/liteeth/liteeth-version.txt @@ -0,0 +1,2 @@ +0.9.0 + diff --git a/misoclib/liteeth/setup.py b/misoclib/liteeth/setup.py new file mode 100644 index 00000000..0f84b945 --- /dev/null +++ b/misoclib/liteeth/setup.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python3 + +import sys, os +from setuptools import setup +from setuptools import find_packages + +here = os.path.abspath(os.path.dirname(__file__)) +README = open(os.path.join(here, "README")).read() + +required_version = (3, 3) +if sys.version_info < required_version: + raise SystemExit("LiteEth requires python {0} or greater".format( + ".".join(map(str, required_version)))) + +setup( + name="liteeth", + version="unknown", + description="small footprint and configurable Ethernet core", + long_description=README, + author="Florent Kermarrec", + author_email="florent@enjoy-digital.fr", + url="http://enjoy-digital.fr", + download_url="https://github.com/enjoy-digital/liteeth", + packages=find_packages(here), + license="GPL", + platforms=["Any"], + keywords="HDL ASIC FPGA hardware design", + classifiers=[ + "Topic :: Scientific/Engineering :: Electronic Design Automation (EDA)", + "Environment :: Console", + "Development Status :: Alpha", + "Intended Audience :: Developers", + "License :: OSI Approved :: GNU General Public License (GPL)", + "Operating System :: OS Independent", + "Programming Language :: Python", + ], +) diff --git a/misoclib/make.py b/misoclib/make.py deleted file mode 100644 index c55c8339..00000000 --- a/misoclib/make.py +++ /dev/null @@ -1,141 +0,0 @@ -#!/usr/bin/env python3 - -import sys, os, argparse, subprocess, struct, importlib - -from mibuild.tools import write_to_file -from migen.util.misc import autotype -from migen.fhdl import verilog, edif -from migen.fhdl.structure import _Fragment -from migen.bank.description import CSRStatus -from mibuild import tools -from mibuild.xilinx_common import * - -from liteeth.common import * - -def get_csr_csv(regions): - r = "" - for name, origin, busword, obj in regions: - if not isinstance(obj, Memory): - for csr in obj: - nr = (csr.size + busword - 1)//busword - r += "{}_{},0x{:08x},{},{}\n".format(name, csr.name, origin, nr, "ro" if isinstance(csr, CSRStatus) else "rw") - origin += 4*nr - return r - -def _import(default, name): - return importlib.import_module(default + "." + name) - -def _get_args(): - parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter, - description="""\ -LiteEth - based on Migen. - -This program builds and/or loads LiteEth components. -One or several actions can be specified: - -clean delete previous build(s). -build-rtl build verilog rtl. -build-bitstream build-bitstream build FPGA bitstream. -build-csr-csv save CSR map into CSV file. - -load-bitstream load bitstream into volatile storage. - -all clean, build-csr-csv, build-bitstream, load-bitstream. -""") - - parser.add_argument("-t", "--target", default="base", help="Core type to build") - parser.add_argument("-s", "--sub-target", default="", help="variant of the Core type to build") - parser.add_argument("-p", "--platform", default=None, help="platform to build for") - parser.add_argument("-Ot", "--target-option", default=[], nargs=2, action="append", help="set target-specific option") - parser.add_argument("-Op", "--platform-option", default=[("programmer", "vivado")], nargs=2, action="append", help="set platform-specific option") - parser.add_argument("--csr_csv", default="./test/csr.csv", help="CSV file to save the CSR map into") - - parser.add_argument("action", nargs="+", help="specify an action") - - return parser.parse_args() - -# Note: misoclib need to be installed as a python library - -if __name__ == "__main__": - args = _get_args() - - # create top-level Core object - target_module = _import("targets", args.target) - if args.sub_target: - top_class = getattr(target_module, args.sub_target) - else: - top_class = target_module.default_subtarget - - if args.platform is None: - platform_name = top_class.default_platform - else: - platform_name = args.platform - platform_module = _import("platforms", platform_name) - platform_kwargs = dict((k, autotype(v)) for k, v in args.platform_option) - platform = platform_module.Platform(**platform_kwargs) - - build_name = top_class.__name__.lower() + "-" + platform_name - top_kwargs = dict((k, autotype(v)) for k, v in args.target_option) - soc = top_class(platform, **top_kwargs) - soc.finalize() - - # decode actions - action_list = ["clean", "build-csr-csv", "build-bitstream", "load-bitstream", "all"] - actions = {k: False for k in action_list} - for action in args.action: - if action in actions: - actions[action] = True - else: - print("Unknown action: "+action+". Valid actions are:") - for a in action_list: - print(" "+a) - sys.exit(1) - - print(""" - __ _ __ ______ __ - / / (_) /____ / __/ /_/ / - / /__/ / __/ -_) _// __/ _ \\ - /____/_/\__/\__/___/\__/_//_/ - - A small footprint and configurable Ethernet - core powered by Migen -====== Building options: ====== -Platform: {} -Target: {} -Subtarget: {} -System Clk: {} MHz -===============================""".format( - platform_name, - args.target, - top_class.__name__, - soc.clk_freq/1000000 - ) -) - - # dependencies - if actions["all"]: - actions["build-csr-csv"] = True - actions["build-bitstream"] = True - actions["load-bitstream"] = True - - if actions["build-bitstream"]: - actions["build-csr-csv"] = True - actions["build-bitstream"] = True - actions["load-bitstream"] = True - - if actions["clean"]: - subprocess.call(["rm", "-rf", "build/*"]) - - if actions["build-csr-csv"]: - csr_csv = get_csr_csv(soc.cpu_csr_regions) - write_to_file(args.csr_csv, csr_csv) - - if actions["build-bitstream"]: - vns = platform.build(soc, build_name=build_name) - if hasattr(soc, "do_exit") and vns is not None: - if hasattr(soc.do_exit, '__call__'): - soc.do_exit(vns) - - if actions["load-bitstream"]: - prog = platform.create_programmer() - prog.load_bitstream("build/" + build_name + platform.bitstream_ext) diff --git a/misoclib/platforms/kc705.py b/misoclib/platforms/kc705.py deleted file mode 100644 index 500d1b07..00000000 --- a/misoclib/platforms/kc705.py +++ /dev/null @@ -1,138 +0,0 @@ -from mibuild.generic_platform import * -from mibuild.crg import SimpleCRG -from mibuild.xilinx_common import CRG_DS -from mibuild.xilinx_ise import XilinxISEPlatform -from mibuild.xilinx_vivado import XilinxVivadoPlatform -from mibuild.programmer import * - -def _run_vivado(cmds): - with subprocess.Popen("vivado -mode tcl", stdin=subprocess.PIPE, shell=True) as process: - process.stdin.write(cmds.encode("ASCII")) - process.communicate() - -class VivadoProgrammer(Programmer): - needs_bitreverse = False - - def load_bitstream(self, bitstream_file): - cmds = """open_hw -connect_hw_server -open_hw_target [lindex [get_hw_targets -of_objects [get_hw_servers localhost]] 0] - -set_property PROBES.FILE {{}} [lindex [get_hw_devices] 0] -set_property PROGRAM.FILE {{{bitstream}}} [lindex [get_hw_devices] 0] - -program_hw_devices [lindex [get_hw_devices] 0] -refresh_hw_device [lindex [get_hw_devices] 0] - -quit -""".format(bitstream=bitstream_file) - _run_vivado(cmds) - - def flash(self, address, data_file): - raise NotImplementedError - -_io = [ - ("user_led", 0, Pins("AB8"), IOStandard("LVCMOS15")), - ("user_led", 1, Pins("AA8"), IOStandard("LVCMOS15")), - ("user_led", 2, Pins("AC9"), IOStandard("LVCMOS15")), - ("user_led", 3, Pins("AB9"), IOStandard("LVCMOS15")), - ("user_led", 4, Pins("AE26"), IOStandard("LVCMOS25")), - ("user_led", 5, Pins("G19"), IOStandard("LVCMOS25")), - ("user_led", 6, Pins("E18"), IOStandard("LVCMOS25")), - ("user_led", 7, Pins("F16"), IOStandard("LVCMOS25")), - - ("cpu_reset", 0, Pins("AB7"), IOStandard("LVCMOS15")), - - ("clk200", 0, - Subsignal("p", Pins("AD12"), IOStandard("LVDS")), - Subsignal("n", Pins("AD11"), IOStandard("LVDS")) - ), - - ("clk156", 0, - Subsignal("p", Pins("K28"), IOStandard("LVDS_25")), - Subsignal("n", Pins("K29"), IOStandard("LVDS_25")) - ), - - - ("serial", 0, - Subsignal("cts", Pins("L27")), - Subsignal("rts", Pins("K23")), - Subsignal("tx", Pins("K24")), - Subsignal("rx", Pins("M19")), - IOStandard("LVCMOS25") - ), - - ("eth_clocks", 0, - Subsignal("tx", Pins("M28")), - Subsignal("gtx", Pins("K30")), - Subsignal("rx", Pins("U27")), - IOStandard("LVCMOS25") - ), - ("eth", 0, - Subsignal("rst_n", Pins("L20")), - Subsignal("int_n", Pins("N30")), - Subsignal("mdio", Pins("J21")), - Subsignal("mdc", Pins("R23")), - Subsignal("dv", Pins("R28")), - Subsignal("rx_er", Pins("V26")), - Subsignal("rx_data", Pins("U30 U25 T25 U28 R19 T27 T26 T28")), - Subsignal("tx_en", Pins("M27")), - Subsignal("tx_er", Pins("N29")), - Subsignal("tx_data", Pins("N27 N25 M29 L28 J26 K26 L30 J28")), - Subsignal("col", Pins("W19")), - Subsignal("crs", Pins("R30")), - IOStandard("LVCMOS25") - ), - -] - -def Platform(*args, toolchain="vivado", programmer="xc3sprog", **kwargs): - if toolchain == "ise": - xilinx_platform = XilinxISEPlatform - elif toolchain == "vivado": - xilinx_platform = XilinxVivadoPlatform - else: - raise ValueError - - class RealPlatform(xilinx_platform): - bitgen_opt = "-g LCK_cycle:6 -g Binary:Yes -w -g ConfigRate:12 -g SPI_buswidth:4" - - def __init__(self, crg_factory=lambda p: CRG_DS(p, "clk200", "cpu_reset")): - xilinx_platform.__init__(self, "xc7k325t-ffg900-2", _io, crg_factory) - - def create_programmer(self): - if programmer == "xc3sprog": - return XC3SProg("jtaghs1_fast", "bscan_spi_kc705.bit") - elif programmer == "vivado": - return VivadoProgrammer() - else: - raise ValueError - - def do_finalize(self, fragment): - try: - self.add_period_constraint(self.lookup_request("clk156").p, 6.4) - except ConstraintError: - pass - try: - self.add_period_constraint(self.lookup_request("clk200").p, 5.0) - except ConstraintError: - pass - try: - self.add_period_constraint(self.lookup_request("eth_clocks").rx, 8.0) - except ConstraintError: - pass - self.add_platform_command(""" -create_clock -name sys_clk -period 6 [get_nets sys_clk] -create_clock -name eth_rx_clk -period 8 [get_nets eth_rx_clk] -create_clock -name eth_tx_clk -period 8 [get_nets eth_tx_clk] - -set_false_path -from [get_clocks sys_clk] -to [get_clocks eth_rx_clk] -set_false_path -from [get_clocks sys_clk] -to [get_clocks eth_tx_clk] -set_false_path -from [get_clocks eth_rx_clk] -to [get_clocks sys_clk] -set_false_path -from [get_clocks eth_tx_clk] -to [get_clocks sys_clk] - -set_property CFGBVS VCCO [current_design] -set_property CONFIG_VOLTAGE 2.5 [current_design] -""") - - return RealPlatform(*args, **kwargs) diff --git a/misoclib/setup.py b/misoclib/setup.py deleted file mode 100644 index 0f84b945..00000000 --- a/misoclib/setup.py +++ /dev/null @@ -1,37 +0,0 @@ -#!/usr/bin/env python3 - -import sys, os -from setuptools import setup -from setuptools import find_packages - -here = os.path.abspath(os.path.dirname(__file__)) -README = open(os.path.join(here, "README")).read() - -required_version = (3, 3) -if sys.version_info < required_version: - raise SystemExit("LiteEth requires python {0} or greater".format( - ".".join(map(str, required_version)))) - -setup( - name="liteeth", - version="unknown", - description="small footprint and configurable Ethernet core", - long_description=README, - author="Florent Kermarrec", - author_email="florent@enjoy-digital.fr", - url="http://enjoy-digital.fr", - download_url="https://github.com/enjoy-digital/liteeth", - packages=find_packages(here), - license="GPL", - platforms=["Any"], - keywords="HDL ASIC FPGA hardware design", - classifiers=[ - "Topic :: Scientific/Engineering :: Electronic Design Automation (EDA)", - "Environment :: Console", - "Development Status :: Alpha", - "Intended Audience :: Developers", - "License :: OSI Approved :: GNU General Public License (GPL)", - "Operating System :: OS Independent", - "Programming Language :: Python", - ], -) diff --git a/misoclib/targets/__init__.py b/misoclib/targets/__init__.py deleted file mode 100644 index 85efe5d9..00000000 --- a/misoclib/targets/__init__.py +++ /dev/null @@ -1,26 +0,0 @@ -import subprocess - -from migen.fhdl.std import * -from migen.bank.description import * - -def get_id(): - output = subprocess.check_output(["git", "rev-parse", "HEAD"]).decode("ascii") - return int(output[:8], 16) - -class Identifier(Module, AutoCSR): - def __init__(self, sysid, frequency, revision=None): - self._r_sysid = CSRStatus(16) - self._r_revision = CSRStatus(32) - self._r_frequency = CSRStatus(32) - - ### - - if revision is None: - revision = get_id() - - self.comb += [ - self._r_sysid.status.eq(sysid), - self._r_revision.status.eq(revision), - self._r_frequency.status.eq(frequency), - ] - diff --git a/misoclib/targets/base.py b/misoclib/targets/base.py deleted file mode 100644 index 3fe1f2a4..00000000 --- a/misoclib/targets/base.py +++ /dev/null @@ -1,224 +0,0 @@ -import os - -from migen.bank import csrgen -from migen.bus import wishbone, csr -from migen.bus import wishbone2csr -from migen.genlib.cdc import * -from migen.genlib.resetsync import AsyncResetSynchronizer -from migen.bank.description import * - -from targets import * - -from litescope.common import * -from litescope.bridge.uart2wb import LiteScopeUART2WB -from litescope.frontend.la import LiteScopeLA -from litescope.core.port import LiteScopeTerm - -from liteeth.common import * -from liteeth.generic import * -from liteeth.phy.gmii import LiteEthPHYGMII -from liteeth.core import LiteEthUDPIPCore - -class _CRG(Module): - def __init__(self, platform): - self.clock_domains.cd_sys = ClockDomain() - self.reset = Signal() - - clk200 = platform.request("clk200") - clk200_se = Signal() - self.specials += Instance("IBUFDS", i_I=clk200.p, i_IB=clk200.n, o_O=clk200_se) - - pll_locked = Signal() - pll_fb = Signal() - pll_sys = Signal() - self.specials += [ - Instance("PLLE2_BASE", - p_STARTUP_WAIT="FALSE", o_LOCKED=pll_locked, - - # VCO @ 1GHz - p_REF_JITTER1=0.01, p_CLKIN1_PERIOD=5.0, - p_CLKFBOUT_MULT=5, p_DIVCLK_DIVIDE=1, - i_CLKIN1=clk200_se, i_CLKFBIN=pll_fb, o_CLKFBOUT=pll_fb, - - # 166MHz - p_CLKOUT0_DIVIDE=6, p_CLKOUT0_PHASE=0.0, o_CLKOUT0=pll_sys, - - p_CLKOUT1_DIVIDE=2, p_CLKOUT1_PHASE=0.0, #o_CLKOUT1=, - - p_CLKOUT2_DIVIDE=2, p_CLKOUT2_PHASE=0.0, #o_CLKOUT2=, - - p_CLKOUT3_DIVIDE=2, p_CLKOUT3_PHASE=0.0, #o_CLKOUT3=, - - p_CLKOUT4_DIVIDE=2, p_CLKOUT4_PHASE=0.0, #o_CLKOUT4= - ), - Instance("BUFG", i_I=pll_sys, o_O=self.cd_sys.clk), - AsyncResetSynchronizer(self.cd_sys, ~pll_locked | platform.request("cpu_reset") | self.reset), - ] - -class GenSoC(Module): - csr_base = 0x00000000 - csr_data_width = 32 - csr_map = { - "bridge": 0, - "identifier": 1, - } - interrupt_map = {} - cpu_type = None - def __init__(self, platform, clk_freq): - self.clk_freq = clk_freq - # UART <--> Wishbone bridge - self.submodules.bridge = LiteScopeUART2WB(platform.request("serial"), clk_freq, baud=921600) - - # CSR bridge 0x00000000 (shadow @0x00000000) - self.submodules.wishbone2csr = wishbone2csr.WB2CSR(bus_csr=csr.Interface(self.csr_data_width)) - self._wb_masters = [self.bridge.wishbone] - self._wb_slaves = [(lambda a: a[23:25] == 0, self.wishbone2csr.wishbone)] - self.cpu_csr_regions = [] # list of (name, origin, busword, csr_list/Memory) - - # CSR - self.submodules.identifier = Identifier(0, int(clk_freq), 0) - - def add_wb_master(self, wbm): - if self.finalized: - raise FinalizeError - self._wb_masters.append(wbm) - - def add_wb_slave(self, address_decoder, interface): - if self.finalized: - raise FinalizeError - self._wb_slaves.append((address_decoder, interface)) - - def add_cpu_memory_region(self, name, origin, length): - self.cpu_memory_regions.append((name, origin, length)) - - def add_cpu_csr_region(self, name, origin, busword, obj): - self.cpu_csr_regions.append((name, origin, busword, obj)) - - def do_finalize(self): - # Wishbone - self.submodules.wishbonecon = wishbone.InterconnectShared(self._wb_masters, - self._wb_slaves, register=True) - - # CSR - self.submodules.csrbankarray = csrgen.BankArray(self, - lambda name, memory: self.csr_map[name if memory is None else name + "_" + memory.name_override], - data_width=self.csr_data_width) - self.submodules.csrcon = csr.Interconnect(self.wishbone2csr.csr, self.csrbankarray.get_buses()) - for name, csrs, mapaddr, rmap in self.csrbankarray.banks: - self.add_cpu_csr_region(name, 0xe0000000+0x800*mapaddr, flen(rmap.bus.dat_w), csrs) - for name, memory, mapaddr, mmap in self.csrbankarray.srams: - self.add_cpu_csr_region(name, 0xe0000000+0x800*mapaddr, flen(rmap.bus.dat_w), memory) - -class BaseSoC(GenSoC, AutoCSR): - default_platform = "kc705" - csr_map = { - "phy": 11, - "core": 12 - } - csr_map.update(GenSoC.csr_map) - def __init__(self, platform, clk_freq=166*1000000, - mac_address=0x10e2d5000000, - ip_address="192.168.1.40"): - GenSoC.__init__(self, platform, clk_freq) - self.submodules.crg = _CRG(platform) - - # wishbone SRAM (to test Wishbone over UART and Etherbone) - self.submodules.sram = wishbone.SRAM(1024) - self.add_wb_slave(lambda a: a[23:25] == 1, self.sram.bus) - - # ethernet PHY and UDP/IP stack - self.submodules.phy = LiteEthPHYGMII(platform.request("eth_clocks"), platform.request("eth")) - self.submodules.core = LiteEthUDPIPCore(self.phy, mac_address, convert_ip(ip_address), clk_freq) - -class BaseSoCDevel(BaseSoC, AutoCSR): - csr_map = { - "la": 20 - } - csr_map.update(BaseSoC.csr_map) - def __init__(self, platform): - BaseSoC.__init__(self, platform) - - self.core_icmp_rx_fsm_state = Signal(4) - self.core_icmp_tx_fsm_state = Signal(4) - self.core_udp_rx_fsm_state = Signal(4) - self.core_udp_tx_fsm_state = Signal(4) - self.core_ip_rx_fsm_state = Signal(4) - self.core_ip_tx_fsm_state = Signal(4) - self.core_arp_rx_fsm_state = Signal(4) - self.core_arp_tx_fsm_state = Signal(4) - self.core_arp_table_fsm_state = Signal(4) - - debug = ( - # MAC interface - self.core.mac.core.sink.stb, - self.core.mac.core.sink.sop, - self.core.mac.core.sink.eop, - self.core.mac.core.sink.ack, - self.core.mac.core.sink.data, - - self.core.mac.core.source.stb, - self.core.mac.core.source.sop, - self.core.mac.core.source.eop, - self.core.mac.core.source.ack, - self.core.mac.core.source.data, - - # ICMP interface - self.core.icmp.echo.sink.stb, - self.core.icmp.echo.sink.sop, - self.core.icmp.echo.sink.eop, - self.core.icmp.echo.sink.ack, - self.core.icmp.echo.sink.data, - - self.core.icmp.echo.source.stb, - self.core.icmp.echo.source.sop, - self.core.icmp.echo.source.eop, - self.core.icmp.echo.source.ack, - self.core.icmp.echo.source.data, - - # IP interface - self.core.ip.crossbar.master.sink.stb, - self.core.ip.crossbar.master.sink.sop, - self.core.ip.crossbar.master.sink.eop, - self.core.ip.crossbar.master.sink.ack, - self.core.ip.crossbar.master.sink.data, - self.core.ip.crossbar.master.sink.ip_address, - self.core.ip.crossbar.master.sink.protocol, - - # State machines - self.core_icmp_rx_fsm_state, - self.core_icmp_tx_fsm_state, - - self.core_arp_rx_fsm_state, - self.core_arp_tx_fsm_state, - self.core_arp_table_fsm_state, - - self.core_ip_rx_fsm_state, - self.core_ip_tx_fsm_state, - - self.core_udp_rx_fsm_state, - self.core_udp_tx_fsm_state - ) - self.submodules.la = LiteScopeLA(debug, 4096) - self.la.trigger.add_port(LiteScopeTerm(self.la.dw)) - - def do_finalize(self): - BaseSoC.do_finalize(self) - self.comb += [ - self.core_icmp_rx_fsm_state.eq(self.core.icmp.rx.fsm.state), - self.core_icmp_tx_fsm_state.eq(self.core.icmp.tx.fsm.state), - - self.core_arp_rx_fsm_state.eq(self.core.arp.rx.fsm.state), - self.core_arp_tx_fsm_state.eq(self.core.arp.tx.fsm.state), - self.core_arp_table_fsm_state.eq(self.core.arp.table.fsm.state), - - self.core_ip_rx_fsm_state.eq(self.core.ip.rx.fsm.state), - self.core_ip_tx_fsm_state.eq(self.core.ip.tx.fsm.state), - - self.core_udp_rx_fsm_state.eq(self.core.udp.rx.fsm.state), - self.core_udp_tx_fsm_state.eq(self.core.udp.tx.fsm.state) - ] - - def do_exit(self, vns): - self.la.export(vns, "test/la.csv") - -default_subtarget = BaseSoC diff --git a/misoclib/targets/etherbone.py b/misoclib/targets/etherbone.py deleted file mode 100644 index 0aaaf2d2..00000000 --- a/misoclib/targets/etherbone.py +++ /dev/null @@ -1,71 +0,0 @@ -from litescope.common import * -from litescope.frontend.la import LiteScopeLA -from litescope.core.port import LiteScopeTerm - -from liteeth.common import * -from liteeth.generic import * - -from targets.base import BaseSoC -from liteeth.core.etherbone import LiteEthEtherbone - -class EtherboneSoC(BaseSoC): - default_platform = "kc705" - def __init__(self, platform): - BaseSoC.__init__(self, platform, - mac_address=0x10e2d5000000, - ip_address="192.168.1.40") - self.submodules.etherbone = LiteEthEtherbone(self.core.udp, 20000) - self.add_wb_master(self.etherbone.master.bus) - -class EtherboneSoCDevel(EtherboneSoC): - csr_map = { - "la": 20 - } - csr_map.update(EtherboneSoC.csr_map) - def __init__(self, platform): - EtherboneSoC.__init__(self, platform) - debug = ( - # mmap stream from HOST - self.etherbone.master.sink.stb, - self.etherbone.master.sink.sop, - self.etherbone.master.sink.eop, - self.etherbone.master.sink.ack, - self.etherbone.master.sink.we, - self.etherbone.master.sink.count, - self.etherbone.master.sink.base_addr, - self.etherbone.master.sink.be, - self.etherbone.master.sink.addr, - self.etherbone.master.sink.data, - - # mmap stream to HOST - self.etherbone.master.source.stb, - self.etherbone.master.source.sop, - self.etherbone.master.source.eop, - self.etherbone.master.source.ack, - self.etherbone.master.source.we, - self.etherbone.master.source.count, - self.etherbone.master.source.base_addr, - self.etherbone.master.source.be, - self.etherbone.master.source.addr, - self.etherbone.master.source.data, - - # etherbone wishbone master - self.etherbone.master.bus.dat_w, - self.etherbone.master.bus.dat_r, - self.etherbone.master.bus.adr, - self.etherbone.master.bus.sel, - self.etherbone.master.bus.cyc, - self.etherbone.master.bus.stb, - self.etherbone.master.bus.ack, - self.etherbone.master.bus.we, - self.etherbone.master.bus.cti, - self.etherbone.master.bus.bte, - self.etherbone.master.bus.err - ) - self.submodules.la = LiteScopeLA(debug, 4096) - self.la.trigger.add_port(LiteScopeTerm(self.la.dw)) - - def do_exit(self, vns): - self.la.export(vns, "test/la.csv") - -default_subtarget = EtherboneSoC diff --git a/misoclib/targets/tty.py b/misoclib/targets/tty.py deleted file mode 100644 index 28cda9d8..00000000 --- a/misoclib/targets/tty.py +++ /dev/null @@ -1,42 +0,0 @@ -from litescope.common import * -from litescope.frontend.la import LiteScopeLA -from litescope.core.port import LiteScopeTerm - -from liteeth.common import * -from liteeth.generic import * - -from targets.base import BaseSoC -from liteeth.core.tty import LiteEthTTY - -class TTYSoC(BaseSoC): - default_platform = "kc705" - def __init__(self, platform): - BaseSoC.__init__(self, platform, - mac_address=0x10e2d5000000, - ip_address="192.168.1.40") - self.submodules.tty = LiteEthTTY(self.core.udp, convert_ip("192.168.1.12"), 10000) - self.comb += Record.connect(self.tty.source, self.tty.sink) - -class TTYSoCDevel(TTYSoC): - csr_map = { - "la": 20 - } - csr_map.update(TTYSoC.csr_map) - def __init__(self, platform): - TTYSoC.__init__(self, platform) - debug = ( - self.tty.sink.stb, - self.tty.sink.ack, - self.tty.sink.data, - - self.tty.source.stb, - self.tty.source.ack, - self.tty.source.data - ) - self.submodules.la = LiteScopeLA(debug, 4096) - self.la.trigger.add_port(LiteScopeTerm(self.la.dw)) - - def do_exit(self, vns): - self.la.export(vns, "test/la.csv") - -default_subtarget = TTYSoC diff --git a/misoclib/targets/udp.py b/misoclib/targets/udp.py deleted file mode 100644 index 9ce15ce5..00000000 --- a/misoclib/targets/udp.py +++ /dev/null @@ -1,69 +0,0 @@ -from litescope.common import * -from litescope.frontend.la import LiteScopeLA -from litescope.core.port import LiteScopeTerm - -from liteeth.common import * -from liteeth.generic import * - -from targets.base import BaseSoC - -class UDPSoC(BaseSoC): - default_platform = "kc705" - def __init__(self, platform): - BaseSoC.__init__(self, platform, - mac_address=0x10e2d5000000, - ip_address="192.168.1.40") - - # add udp loopback on port 6000 with dw=8 - self.add_udp_loopback(6000, 8, 8192, "loopback_8") - # add udp loopback on port 8000 with dw=32 - self.add_udp_loopback(8000, 32, 8192, "loopback_32") - - def add_udp_loopback(self, port, dw, depth, name=None): - port = self.core.udp.crossbar.get_port(port, dw) - buf = PacketBuffer(eth_udp_user_description(dw), depth//(dw//8), 8) - if name is None: - self.submodules += buf - else: - setattr(self.submodules, name, buf) - self.comb += Port.connect(port, buf) - -class UDPSoCDevel(UDPSoC): - csr_map = { - "la": 20 - } - csr_map.update(UDPSoC.csr_map) - def __init__(self, platform): - UDPSoC.__init__(self, platform) - debug = ( - self.loopback_8.sink.stb, - self.loopback_8.sink.sop, - self.loopback_8.sink.eop, - self.loopback_8.sink.ack, - self.loopback_8.sink.data, - - self.loopback_8.source.stb, - self.loopback_8.source.sop, - self.loopback_8.source.eop, - self.loopback_8.source.ack, - self.loopback_8.source.data, - - self.loopback_32.sink.stb, - self.loopback_32.sink.sop, - self.loopback_32.sink.eop, - self.loopback_32.sink.ack, - self.loopback_32.sink.data, - - self.loopback_32.source.stb, - self.loopback_32.source.sop, - self.loopback_32.source.eop, - self.loopback_32.source.ack, - self.loopback_32.source.data - ) - self.submodules.la = LiteScopeLA(debug, 4096) - self.la.trigger.add_port(LiteScopeTerm(self.la.dw)) - - def do_exit(self, vns): - self.la.export(vns, "test/la.csv") - -default_subtarget = UDPSoC diff --git a/misoclib/test/make.py b/misoclib/test/make.py deleted file mode 100644 index 05e13aad..00000000 --- a/misoclib/test/make.py +++ /dev/null @@ -1,33 +0,0 @@ -#!/usr/bin/env python3 -import argparse, importlib - -def _get_args(): - parser = argparse.ArgumentParser() - parser.add_argument("-b", "--bridge", default="uart", help="Bridge to use") - parser.add_argument("--port", default=2, help="UART port") - parser.add_argument("--baudrate", default=921600, help="UART baudrate") - parser.add_argument("--ip_address", default="192.168.1.40", help="Etherbone IP address") - parser.add_argument("--udp_port", default=20000, help="Etherbone UDP port") - parser.add_argument("--busword", default=32, help="CSR busword") - - parser.add_argument("test", nargs="+", help="specify a test") - - return parser.parse_args() - -if __name__ == "__main__": - args = _get_args() - if args.bridge == "uart": - from litescope.host.driver.uart import LiteScopeUARTDriver - wb = LiteScopeUARTDriver(args.port, args.baudrate, "./csr.csv", int(args.busword), debug=False) - elif args.bridge == "etherbone": - from litescope.host.driver.etherbone import LiteScopeEtherboneDriver - wb = LiteScopeEtherboneDriver(args.ip_address, int(args.udp_port), "./csr.csv", int(args.busword), debug=False) - else: - ValueError("Invalid bridge {}".format(args.bridge)) - - def _import(name): - return importlib.import_module(name) - - for test in args.test: - t = _import("test_"+test) - t.main(wb) diff --git a/misoclib/test/test_etherbone.py b/misoclib/test/test_etherbone.py deleted file mode 100644 index 4622d524..00000000 --- a/misoclib/test/test_etherbone.py +++ /dev/null @@ -1,60 +0,0 @@ -import socket, time -from liteeth.test.model.etherbone import * - -SRAM_BASE = 0x02000000 - -import socket - -def main(wb): - sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - - # test probe - packet = EtherbonePacket() - packet.pf = 1 - packet.encode() - sock.sendto(bytes(packet), ("192.168.1.40", 20000)) - time.sleep(0.01) - - # test writes - writes_datas = [j for j in range(16)] - writes = EtherboneWrites(base_addr=SRAM_BASE, datas=writes_datas) - record = EtherboneRecord() - record.writes = writes - record.reads = None - record.bca = 0 - record.rca = 0 - record.rff = 0 - record.cyc = 0 - record.wca = 0 - record.wff = 0 - record.byte_enable = 0xf - record.wcount = len(writes_datas) - record.rcount = 0 - - packet = EtherbonePacket() - packet.records = [record] - packet.encode() - sock.sendto(bytes(packet), ("192.168.1.40", 20000)) - time.sleep(0.01) - - # test reads - reads_addrs = [SRAM_BASE+4*j for j in range(16)] - reads = EtherboneReads(base_ret_addr=0x1000, addrs=reads_addrs) - record = EtherboneRecord() - record.writes = None - record.reads = reads - record.bca = 0 - record.rca = 0 - record.rff = 0 - record.cyc = 0 - record.wca = 0 - record.wff = 0 - record.byte_enable = 0xf - record.wcount = 0 - record.rcount = len(reads_addrs) - - packet = EtherbonePacket() - packet.records = [record] - packet.encode() - sock.sendto(bytes(packet), ("192.168.1.40", 20000)) - time.sleep(0.01) diff --git a/misoclib/test/test_la.py b/misoclib/test/test_la.py deleted file mode 100644 index c15de8c8..00000000 --- a/misoclib/test/test_la.py +++ /dev/null @@ -1,24 +0,0 @@ -import time -from litescope.host.driver.la import LiteScopeLADriver - -def main(wb): - la = LiteScopeLADriver(wb.regs, "la", debug=True) - - wb.open() - regs = wb.regs - ### - - conditions = {} - la.configure_term(port=0, cond=conditions) - la.configure_sum("term") - # Run Logic Analyzer - la.run(offset=2048, length=4000) - - while not la.done(): - pass - - la.upload() - la.save("dump.vcd") - - ### - wb.close() diff --git a/misoclib/test/test_regs.py b/misoclib/test/test_regs.py deleted file mode 100644 index f2685cf5..00000000 --- a/misoclib/test/test_regs.py +++ /dev/null @@ -1,12 +0,0 @@ -def main(wb): - wb.open() - regs = wb.regs - ### - print("sysid : 0x%04x" %regs.identifier_sysid.read()) - print("revision : 0x%04x" %regs.identifier_revision.read()) - print("frequency : %d MHz" %(regs.identifier_frequency.read()/1000000)) - SRAM_BASE = 0x02000000 - wb.write(SRAM_BASE, [i for i in range(64)]) - print(wb.read(SRAM_BASE, 64)) - ### - wb.close() diff --git a/misoclib/test/test_tty.py b/misoclib/test/test_tty.py deleted file mode 100644 index af6f2df0..00000000 --- a/misoclib/test/test_tty.py +++ /dev/null @@ -1,36 +0,0 @@ -import socket -import threading - -def test(fpga_ip, udp_port, test_message): - tx_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - rx_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - rx_sock.bind(("", udp_port)) - rx_sock.settimeout(0.5) - - def receive(): - while True: - try: - msg = rx_sock.recv(8192) - for byte in msg: - print(chr(byte), end="") - except: - break - - def send(): - tx_sock.sendto(bytes(test_message, "utf-8"), (fpga_ip, udp_port)) - - receive_thread = threading.Thread(target=receive) - receive_thread.start() - - send_thread = threading.Thread(target=send) - send_thread.start() - - try: - send_thread.join(5) - send_thread.join(5) - except KeyboardInterrupt: - pass - -def main(wb): - test_message = "LiteEth virtual TTY Hello world\n" - test("192.168.1.40", 10000, test_message) diff --git a/misoclib/test/test_udp.py b/misoclib/test/test_udp.py deleted file mode 100644 index 65d47b74..00000000 --- a/misoclib/test/test_udp.py +++ /dev/null @@ -1,81 +0,0 @@ -import socket -import time -import threading -import copy - -KB = 1024 -MB = 1024*KB -GB = 1024*MB - -def seed_to_data(seed, random=True): - if random: - return (seed * 0x31415979 + 1) & 0xffffffff - else: - return seed - -def check(p1, p2): - p1 = copy.deepcopy(p1) - p2 = copy.deepcopy(p2) - if isinstance(p1, int): - return 0, 1, int(p1 != p2) - else: - if len(p1) >= len(p2): - ref, res = p1, p2 - else: - ref, res = p2, p1 - shift = 0 - while((ref[0] != res[0]) and (len(res)>1)): - res.pop(0) - shift += 1 - length = min(len(ref), len(res)) - errors = 0 - for i in range(length): - if ref.pop(0) != res.pop(0): - errors += 1 - return shift, length, errors - -def generate_packet(seed, length): - r = [] - for i in range(length): - r.append(seed_to_data(seed, True)%0xff) # XXX FIXME - seed += 1 - return r, seed - -def test(fpga_ip, udp_port, test_size): - tx_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - rx_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - rx_sock.bind(("", udp_port)) - - def receive(): - rx_seed = 0 - while rx_seed < test_size: - data, addr = rx_sock.recvfrom(8192) - rx_packet = [] - for byte in data: - rx_packet.append(int(byte)) - rx_reference_packet, rx_seed = generate_packet(rx_seed, 1024) - s, l, e = check(rx_reference_packet, rx_packet) - print("shift "+ str(s) + " / length " + str(l) + " / errors " + str(e)) - - def send(): - tx_seed = 0 - while tx_seed < test_size: - tx_packet, tx_seed = generate_packet(tx_seed, 1024) - tx_sock.sendto(bytes(tx_packet), (fpga_ip, udp_port)) - time.sleep(0.001) # XXX: FIXME, Python limitation? - - receive_thread = threading.Thread(target=receive) - receive_thread.start() - - send_thread = threading.Thread(target=send) - send_thread.start() - - try: - send_thread.join(10) - receive_thread.join(0.1) - except KeyboardInterrupt: - pass - -def main(wb): - test("192.168.1.40", 6000, 128*KB) - test("192.168.1.40", 8000, 128*KB)