mirror of
https://github.com/im-tomu/fomu-workshop.git
synced 2024-09-20 03:10:12 +00:00
litex: move examples into litex/ directory
Signed-off-by: Sean Cross <sean@xobs.io>
This commit is contained in:
parent
6862a659f9
commit
ac9e39bdcf
32
.gitmodules
vendored
32
.gitmodules
vendored
@ -1,24 +1,24 @@
|
||||
[submodule "deps/migen"]
|
||||
path = deps/migen
|
||||
[submodule "litex/deps/migen"]
|
||||
path = litex/deps/migen
|
||||
url = https://github.com/m-labs/migen.git
|
||||
[submodule "deps/litex"]
|
||||
path = deps/litex
|
||||
[submodule "litex/deps/litex"]
|
||||
path = litex/deps/litex
|
||||
url = https://github.com/enjoy-digital/litex.git
|
||||
[submodule "deps/litex_boards"]
|
||||
path = deps/litex_boards
|
||||
[submodule "litex/deps/litex_boards"]
|
||||
path = litex/deps/litex_boards
|
||||
url = https://github.com/litex-hub/litex-boards.git
|
||||
[submodule "deps/litescope"]
|
||||
path = deps/litescope
|
||||
[submodule "litex/deps/litescope"]
|
||||
path = litex/deps/litescope
|
||||
url = https://github.com/enjoy-digital/litescope.git
|
||||
[submodule "deps/pyserial"]
|
||||
path = deps/pyserial
|
||||
[submodule "litex/deps/pyserial"]
|
||||
path = litex/deps/pyserial
|
||||
url = https://github.com/pyserial/pyserial.git
|
||||
[submodule "deps/lxsocsupport"]
|
||||
path = deps/lxsocsupport
|
||||
[submodule "litex/deps/lxsocsupport"]
|
||||
path = litex/deps/lxsocsupport
|
||||
url = https://github.com/xobs/lxsocsupport.git
|
||||
[submodule "deps/valentyusb"]
|
||||
path = deps/valentyusb
|
||||
[submodule "litex/deps/valentyusb"]
|
||||
path = litex/deps/valentyusb
|
||||
url = https://github.com/im-tomu/valentyusb.git
|
||||
[submodule "deps/litedram"]
|
||||
path = deps/litedram
|
||||
[submodule "litex/deps/litedram"]
|
||||
path = litex/deps/litedram
|
||||
url = https://github.com/enjoy-digital/litedram.git
|
||||
|
108
litex/workshop.py
Normal file
108
litex/workshop.py
Normal file
@ -0,0 +1,108 @@
|
||||
#!/usr/bin/env python3
|
||||
# This variable defines all the external programs that this module
|
||||
# relies on. lxbuildenv reads this variable in order to ensure
|
||||
# the build will finish without exiting due to missing third-party
|
||||
# programs.
|
||||
LX_DEPENDENCIES = ["riscv", "icestorm"]
|
||||
|
||||
# Import lxbuildenv to integrate the deps/ directory
|
||||
import lxbuildenv
|
||||
|
||||
# Disable pylint's E1101, which breaks completely on migen
|
||||
#pylint:disable=E1101
|
||||
|
||||
from litex_boards.partner.platforms.fomu_evt import Platform
|
||||
from litex_boards.partner.targets.fomu import _CRG
|
||||
|
||||
from litex.soc.integration import SoCCore
|
||||
from litex.soc.integration.builder import Builder
|
||||
|
||||
from lxsocsupport import up5kspram
|
||||
|
||||
from valentyusb.usbcore import io as usbio
|
||||
from valentyusb.usbcore.cpu import dummyusb
|
||||
|
||||
import argparse
|
||||
|
||||
|
||||
class BaseSoC(SoCCore):
|
||||
SoCCore.csr_map = {
|
||||
"ctrl": 0, # provided by default (optional)
|
||||
"crg": 1, # user
|
||||
"uart_phy": 2, # provided by default (optional)
|
||||
"uart": 3, # provided by default (optional)
|
||||
"identifier_mem": 4, # provided by default (optional)
|
||||
"timer0": 5, # provided by default (optional)
|
||||
"cpu_or_bridge": 8,
|
||||
"usb": 9,
|
||||
"picorvspi": 10,
|
||||
"touch": 11,
|
||||
"reboot": 12,
|
||||
"rgb": 13,
|
||||
"version": 14,
|
||||
}
|
||||
|
||||
def __init__(self, platform, output_dir="build", placer=None, pnr_seed=0, use_pll=True, **kwargs):
|
||||
clk_freq = int(12e6)
|
||||
self.submodules.crg = _CRG(platform, use_pll=use_pll)
|
||||
SoCCore.__init__(self, platform, clk_freq,
|
||||
cpu_type=None,
|
||||
cpu_variant=None,
|
||||
integrated_sram_size=0,
|
||||
with_uart=False,
|
||||
with_ctrl=False,
|
||||
**kwargs)
|
||||
|
||||
# UP5K has single port RAM, which is a dedicated 128 kilobyte block.
|
||||
# Use this as CPU RAM.
|
||||
spram_size = 128*1024
|
||||
self.submodules.spram = up5kspram.Up5kSPRAM(size=spram_size)
|
||||
self.register_mem("sram", 0x10000000, self.spram.bus, spram_size)
|
||||
|
||||
# Add USB pads. We use DummyUsb, which simply enumerates as a USB
|
||||
# device. Then all interaction is done via the wishbone bridge.
|
||||
usb_pads = platform.request("usb")
|
||||
usb_iobuf = usbio.IoBuf(usb_pads.d_p, usb_pads.d_n, usb_pads.pullup)
|
||||
self.submodules.usb = dummyusb.DummyUsb(usb_iobuf, debug=True)
|
||||
self.add_wb_master(self.usb.debug_bridge.wishbone)
|
||||
|
||||
# Add "-relut -dffe_min_ce_use 4" to the synth_ice40 command.
|
||||
# "-reult" adds an additional LUT pass to pack more stuff in, and
|
||||
# "-dffe_min_ce_use 4" flag prevents Yosys from generating a
|
||||
# Clock Enable signal for a LUT that has fewer than 4 flip-flops.
|
||||
# This increases density, and lets us use the FPGA more efficiently.
|
||||
platform.toolchain.nextpnr_yosys_template[2] += " -relut -dffe_min_ce_use 4"
|
||||
|
||||
# Allow us to set the nextpnr seed, because some values don't meet timing.
|
||||
platform.toolchain.nextpnr_build_template[1] += " --seed " + str(pnr_seed)
|
||||
|
||||
# Different placers can improve packing efficiency, however not all placers
|
||||
# are enabled on all builds of nextpnr-ice40. Let the user override which
|
||||
# placer they want to use.
|
||||
if placer is not None:
|
||||
platform.toolchain.nextpnr_build_template[1] += " --placer {}".format(placer)
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Build Fomu Main Gateware")
|
||||
parser.add_argument(
|
||||
"--seed", default=0, help="seed to use in nextpnr"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--placer", choices=["sa", "heap"], help="which placer to use in nextpnr"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--no-pll", help="disable pll -- this is easier to route, but may not work", action="store_true"
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
platform = Platform()
|
||||
soc = BaseSoC(platform, pnr_seed=args.seed, placer=args.placer, use_pll=not args.no_pll)
|
||||
builder = Builder(soc,
|
||||
output_dir="build", csr_csv="test/csr.csv",
|
||||
compile_software=False)
|
||||
vns = builder.build()
|
||||
soc.do_exit(vns)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
366
workshop.py
366
workshop.py
@ -1,366 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
# This variable defines all the external programs that this module
|
||||
# relies on. lxbuildenv reads this variable in order to ensure
|
||||
# the build will finish without exiting due to missing third-party
|
||||
# programs.
|
||||
LX_DEPENDENCIES = ["riscv", "icestorm"]
|
||||
|
||||
# Import lxbuildenv to integrate the deps/ directory
|
||||
import lxbuildenv
|
||||
# "python.autoComplete.extraPaths": [
|
||||
# "deps/litescope",
|
||||
# "deps/litex",
|
||||
# "deps/litex_boards",
|
||||
# "deps/lxsocsupport",
|
||||
# "deps/migen",
|
||||
# "deps/valentyusb"
|
||||
# ]
|
||||
|
||||
# Disable pylint's E1101, which breaks completely on migen
|
||||
#pylint:disable=E1101
|
||||
|
||||
from migen import Module, Signal, Instance, ClockDomain, If
|
||||
from migen.genlib.resetsync import AsyncResetSynchronizer
|
||||
from migen.fhdl.specials import TSTriple
|
||||
from migen.fhdl.bitcontainer import bits_for
|
||||
from migen.fhdl.structure import ClockSignal, ResetSignal, Replicate, Cat
|
||||
|
||||
from litex_boards.partner.platforms.fomu_pvt import Platform
|
||||
|
||||
from litex.soc.integration import SoCCore
|
||||
from litex.soc.integration.builder import Builder
|
||||
from litex.soc.integration.soc_core import csr_map_update
|
||||
from litex.soc.interconnect import wishbone
|
||||
from litex.soc.interconnect.csr import AutoCSR, CSRStatus, CSRStorage
|
||||
|
||||
from lxsocsupport import up5kspram
|
||||
|
||||
from valentyusb import usbcore
|
||||
from valentyusb.usbcore import io as usbio
|
||||
from valentyusb.usbcore.cpu import dummyusb
|
||||
|
||||
import argparse
|
||||
|
||||
class _CRG(Module):
|
||||
def __init__(self, platform, use_pll):
|
||||
clk48_raw = platform.request("clk48")
|
||||
clk12_raw = Signal()
|
||||
clk48 = Signal()
|
||||
clk12 = Signal()
|
||||
|
||||
reset_delay = Signal(13, reset=4095)
|
||||
self.clock_domains.cd_por = ClockDomain()
|
||||
self.reset = Signal()
|
||||
|
||||
self.clock_domains.cd_sys = ClockDomain()
|
||||
self.clock_domains.cd_usb_12 = ClockDomain()
|
||||
self.clock_domains.cd_usb_48 = ClockDomain()
|
||||
|
||||
platform.add_period_constraint(self.cd_usb_48.clk, 1e9/48e6)
|
||||
platform.add_period_constraint(self.cd_sys.clk, 1e9/12e6)
|
||||
platform.add_period_constraint(self.cd_usb_12.clk, 1e9/12e6)
|
||||
platform.add_period_constraint(clk48, 1e9/48e6)
|
||||
platform.add_period_constraint(clk48_raw, 1e9/48e6)
|
||||
platform.add_period_constraint(clk12_raw, 1e9/12e6)
|
||||
|
||||
# POR reset logic- POR generated from sys clk, POR logic feeds sys clk
|
||||
# reset.
|
||||
self.comb += [
|
||||
self.cd_por.clk.eq(self.cd_sys.clk),
|
||||
self.cd_sys.rst.eq(reset_delay != 0),
|
||||
self.cd_usb_12.rst.eq(reset_delay != 0),
|
||||
]
|
||||
|
||||
if use_pll:
|
||||
|
||||
# Divide clk48 down to clk12, to ensure they're synchronized.
|
||||
# By doing this, we avoid needing clock-domain crossing.
|
||||
clk12_counter = Signal(2)
|
||||
|
||||
self.clock_domains.cd_usb_48_raw = ClockDomain()
|
||||
|
||||
platform.add_period_constraint(self.cd_usb_48_raw.clk, 1e9/48e6)
|
||||
|
||||
# POR reset logic- POR generated from sys clk, POR logic feeds sys clk
|
||||
# reset.
|
||||
self.comb += [
|
||||
self.cd_usb_48.rst.eq(reset_delay != 0),
|
||||
]
|
||||
|
||||
self.comb += self.cd_usb_48_raw.clk.eq(clk48_raw)
|
||||
self.comb += self.cd_usb_48.clk.eq(clk48)
|
||||
|
||||
self.sync.usb_48_raw += clk12_counter.eq(clk12_counter + 1)
|
||||
|
||||
self.comb += clk12_raw.eq(clk12_counter[1])
|
||||
self.specials += Instance(
|
||||
"SB_GB",
|
||||
i_USER_SIGNAL_TO_GLOBAL_BUFFER=clk12_raw,
|
||||
o_GLOBAL_BUFFER_OUTPUT=clk12,
|
||||
)
|
||||
|
||||
self.specials += Instance(
|
||||
"SB_PLL40_CORE",
|
||||
# Parameters
|
||||
p_DIVR = 0,
|
||||
p_DIVF = 3,
|
||||
p_DIVQ = 2,
|
||||
p_FILTER_RANGE = 1,
|
||||
p_FEEDBACK_PATH = "PHASE_AND_DELAY",
|
||||
p_DELAY_ADJUSTMENT_MODE_FEEDBACK = "FIXED",
|
||||
p_FDA_FEEDBACK = 15,
|
||||
p_DELAY_ADJUSTMENT_MODE_RELATIVE = "FIXED",
|
||||
p_FDA_RELATIVE = 0,
|
||||
p_SHIFTREG_DIV_MODE = 1,
|
||||
p_PLLOUT_SELECT = "SHIFTREG_0deg",
|
||||
p_ENABLE_ICEGATE = 0,
|
||||
# IO
|
||||
i_REFERENCECLK = clk12,
|
||||
o_PLLOUTGLOBAL = clk48,
|
||||
i_BYPASS = 0,
|
||||
i_RESETB = 1,
|
||||
)
|
||||
else:
|
||||
self.specials += Instance(
|
||||
"SB_GB",
|
||||
i_USER_SIGNAL_TO_GLOBAL_BUFFER=clk48_raw,
|
||||
o_GLOBAL_BUFFER_OUTPUT=clk48,
|
||||
)
|
||||
self.comb += self.cd_usb_48.clk.eq(clk48)
|
||||
|
||||
clk12_counter = Signal(2)
|
||||
self.sync.usb_48 += clk12_counter.eq(clk12_counter + 1)
|
||||
|
||||
self.comb += clk12_raw.eq(clk12_counter[1])
|
||||
self.specials += Instance(
|
||||
"SB_GB",
|
||||
i_USER_SIGNAL_TO_GLOBAL_BUFFER=clk12_raw,
|
||||
o_GLOBAL_BUFFER_OUTPUT=clk12,
|
||||
)
|
||||
|
||||
self.comb += self.cd_sys.clk.eq(clk12)
|
||||
self.comb += self.cd_usb_12.clk.eq(clk12)
|
||||
|
||||
self.sync.por += \
|
||||
If(reset_delay != 0,
|
||||
reset_delay.eq(reset_delay - 1)
|
||||
)
|
||||
self.specials += AsyncResetSynchronizer(self.cd_por, self.reset)
|
||||
|
||||
class PicoRVSpi(Module, AutoCSR):
|
||||
def __init__(self, platform, pads, size=2*1024*1024):
|
||||
self.size = size
|
||||
|
||||
self.bus = bus = wishbone.Interface()
|
||||
|
||||
self.reset = Signal()
|
||||
|
||||
self.cfg1 = CSRStorage(size=8)
|
||||
self.cfg2 = CSRStorage(size=8)
|
||||
self.cfg3 = CSRStorage(size=8)
|
||||
self.cfg4 = CSRStorage(size=8, reset=0x80)
|
||||
|
||||
self.stat1 = CSRStatus(size=8)
|
||||
self.stat2 = CSRStatus(size=8)
|
||||
self.stat3 = CSRStatus(size=8)
|
||||
self.stat4 = CSRStatus(size=8)
|
||||
|
||||
cfg = Signal(32)
|
||||
cfg_we = Signal(4)
|
||||
cfg_out = Signal(32)
|
||||
self.comb += [
|
||||
cfg.eq(Cat(self.cfg1.storage, self.cfg2.storage, self.cfg3.storage, self.cfg4.storage)),
|
||||
cfg_we.eq(Cat(self.cfg1.re, self.cfg2.re, self.cfg3.re, self.cfg4.re)),
|
||||
self.stat1.status.eq(cfg_out[0:8]),
|
||||
self.stat2.status.eq(cfg_out[8:16]),
|
||||
self.stat3.status.eq(cfg_out[16:24]),
|
||||
self.stat4.status.eq(cfg_out[24:32]),
|
||||
]
|
||||
|
||||
mosi_pad = TSTriple()
|
||||
miso_pad = TSTriple()
|
||||
cs_n_pad = TSTriple()
|
||||
clk_pad = TSTriple()
|
||||
wp_pad = TSTriple()
|
||||
hold_pad = TSTriple()
|
||||
self.specials += mosi_pad.get_tristate(pads.mosi)
|
||||
self.specials += miso_pad.get_tristate(pads.miso)
|
||||
self.specials += cs_n_pad.get_tristate(pads.cs_n)
|
||||
self.specials += clk_pad.get_tristate(pads.clk)
|
||||
self.specials += wp_pad.get_tristate(pads.wp)
|
||||
self.specials += hold_pad.get_tristate(pads.hold)
|
||||
|
||||
reset = Signal()
|
||||
self.comb += [
|
||||
reset.eq(ResetSignal() | self.reset),
|
||||
cs_n_pad.oe.eq(~reset),
|
||||
clk_pad.oe.eq(~reset),
|
||||
]
|
||||
|
||||
flash_addr = Signal(24)
|
||||
mem_bits = bits_for(size)
|
||||
self.comb += flash_addr.eq(bus.adr[0:mem_bits-2] << 2),
|
||||
|
||||
read_active = Signal()
|
||||
spi_ready = Signal()
|
||||
self.sync += [
|
||||
If(bus.stb & bus.cyc & ~read_active,
|
||||
read_active.eq(1),
|
||||
bus.ack.eq(0),
|
||||
)
|
||||
.Elif(read_active & spi_ready,
|
||||
read_active.eq(0),
|
||||
bus.ack.eq(1),
|
||||
)
|
||||
.Else(
|
||||
bus.ack.eq(0),
|
||||
read_active.eq(0),
|
||||
)
|
||||
]
|
||||
|
||||
o_rdata = Signal(32)
|
||||
self.comb += bus.dat_r.eq(o_rdata)
|
||||
|
||||
self.specials += Instance("spimemio",
|
||||
o_flash_io0_oe = mosi_pad.oe,
|
||||
o_flash_io1_oe = miso_pad.oe,
|
||||
o_flash_io2_oe = wp_pad.oe,
|
||||
o_flash_io3_oe = hold_pad.oe,
|
||||
|
||||
o_flash_io0_do = mosi_pad.o,
|
||||
o_flash_io1_do = miso_pad.o,
|
||||
o_flash_io2_do = wp_pad.o,
|
||||
o_flash_io3_do = hold_pad.o,
|
||||
o_flash_csb = cs_n_pad.o,
|
||||
o_flash_clk = clk_pad.o,
|
||||
|
||||
i_flash_io0_di = mosi_pad.i,
|
||||
i_flash_io1_di = miso_pad.i,
|
||||
i_flash_io2_di = wp_pad.i,
|
||||
i_flash_io3_di = hold_pad.i,
|
||||
|
||||
i_resetn = ~reset,
|
||||
i_clk = ClockSignal(),
|
||||
|
||||
i_valid = bus.stb & bus.cyc,
|
||||
o_ready = spi_ready,
|
||||
i_addr = flash_addr,
|
||||
o_rdata = o_rdata,
|
||||
|
||||
i_cfgreg_we = cfg_we,
|
||||
i_cfgreg_di = cfg,
|
||||
o_cfgreg_do = cfg_out,
|
||||
)
|
||||
platform.add_source("rtl/spimemio.v")
|
||||
|
||||
class BaseSoC(SoCCore):
|
||||
csr_peripherals = [
|
||||
"ddrphy",
|
||||
# "dna",
|
||||
"xadc",
|
||||
"cpu_or_bridge",
|
||||
]
|
||||
SoCCore.csr_map = {
|
||||
"ctrl": 0, # provided by default (optional)
|
||||
"crg": 1, # user
|
||||
"uart_phy": 2, # provided by default (optional)
|
||||
"uart": 3, # provided by default (optional)
|
||||
"identifier_mem": 4, # provided by default (optional)
|
||||
"timer0": 5, # provided by default (optional)
|
||||
"cpu_or_bridge": 8,
|
||||
"usb": 9,
|
||||
"picorvspi": 10,
|
||||
"touch": 11,
|
||||
"reboot": 12,
|
||||
"rgb": 13,
|
||||
"version": 14,
|
||||
}
|
||||
|
||||
mem_map = {
|
||||
"spiflash": 0x20000000, # (default shadow @0xa0000000)
|
||||
}
|
||||
mem_map.update(SoCCore.mem_map)
|
||||
|
||||
def __init__(self, platform, output_dir="build", placer=None, pnr_seed=0, use_pll=True, **kwargs):
|
||||
clk_freq = int(12e6)
|
||||
self.output_dir = output_dir
|
||||
self.submodules.crg = _CRG(platform, use_pll=use_pll)
|
||||
SoCCore.__init__(self, platform, clk_freq,
|
||||
cpu_type=None, cpu_variant=None,
|
||||
integrated_sram_size=0, with_uart=False,
|
||||
**kwargs)
|
||||
|
||||
# SPRAM- UP5K has single port RAM, might as well use it as SRAM to
|
||||
# free up scarce block RAM.
|
||||
spram_size = 128*1024
|
||||
self.submodules.spram = up5kspram.Up5kSPRAM(size=spram_size)
|
||||
self.register_mem("sram", 0x10000000, self.spram.bus, spram_size)
|
||||
|
||||
# Add a simple bit-banged SPI Flash module based on PicoRVSpi
|
||||
spi_pads = platform.request("spiflash")
|
||||
self.submodules.picorvspi = PicoRVSpi(platform, spi_pads)
|
||||
self.register_mem("spiflash", self.mem_map["spiflash"],
|
||||
self.picorvspi.bus, size=self.picorvspi.size)
|
||||
|
||||
usb_pads = platform.request("usb")
|
||||
usb_iobuf = usbio.IoBuf(usb_pads.d_p, usb_pads.d_n, usb_pads.pullup)
|
||||
self.submodules.usb = dummyusb.DummyUsb(usb_iobuf, debug=True)
|
||||
self.add_wb_master(self.usb.debug_bridge.wishbone)
|
||||
|
||||
if hasattr(self, "cpu"):
|
||||
self.cpu.use_external_variant("rtl/2-stage-1024-cache.v")
|
||||
self.copy_memory_file("2-stage-1024-cache.v_toplevel_RegFilePlugin_regFile.bin")
|
||||
bios_size = 0x8000
|
||||
kwargs['cpu_reset_address']=self.mem_map["spiflash"]+platform.gateware_size
|
||||
self.add_memory_region("rom", kwargs['cpu_reset_address'], bios_size)
|
||||
self.add_constant("ROM_DISABLE", 1)
|
||||
self.flash_boot_address = self.mem_map["spiflash"]+platform.gateware_size+bios_size
|
||||
self.add_memory_region("user_flash",
|
||||
self.flash_boot_address,
|
||||
# Leave a grace area- possible one-by-off bug in add_memory_region?
|
||||
# Possible fix: addr < origin + length - 1
|
||||
platform.spiflash_total_size - (self.flash_boot_address - self.mem_map["spiflash"]) - 0x100)
|
||||
|
||||
# Add "-relut -dffe_min_ce_use 4" to the synth_ice40 command.
|
||||
# The "-reult" adds an additional LUT pass to pack more stuff in,
|
||||
# and the "-dffe_min_ce_use 4" flag prevents Yosys from generating a
|
||||
# Clock Enable signal for a LUT that has fewer than 4 flip-flops.
|
||||
# This increases density, and lets us use the FPGA more efficiently.
|
||||
platform.toolchain.nextpnr_yosys_template[2] += " -relut -dffe_min_ce_use 5"
|
||||
|
||||
# Allow us to set the nextpnr seed
|
||||
platform.toolchain.nextpnr_build_template[1] += " --seed " + str(pnr_seed)
|
||||
|
||||
if placer is not None:
|
||||
platform.toolchain.nextpnr_build_template[1] += " --placer {}".format(placer)
|
||||
|
||||
def copy_memory_file(self, src):
|
||||
import os
|
||||
from shutil import copyfile
|
||||
if not os.path.exists(self.output_dir):
|
||||
os.mkdir(self.output_dir)
|
||||
if not os.path.exists(os.path.join(self.output_dir, "gateware")):
|
||||
os.mkdir(os.path.join(self.output_dir, "gateware"))
|
||||
copyfile(os.path.join("rtl", src), os.path.join(self.output_dir, "gateware", src))
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Build Fomu Main Gateware")
|
||||
parser.add_argument(
|
||||
"--seed", default=0, help="seed to use in nextpnr"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--placer", choices=["sa", "heap"], help="which placer to use in nextpnr"
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
platform = Platform()
|
||||
soc = BaseSoC(platform, pnr_seed=args.seed, placer=args.placer)
|
||||
builder = Builder(soc,
|
||||
output_dir="build", csr_csv="test/csr.csv",
|
||||
compile_software=False)
|
||||
vns = builder.build()
|
||||
soc.do_exit(vns)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
Loading…
Reference in New Issue
Block a user