mirror of
https://github.com/enjoy-digital/litex.git
synced 2025-01-04 09:52:26 -05:00
mibuild: add initial Lattice Diamond support (with ECP3 Versa board platform skeleton)
This commit is contained in:
parent
beeaefccea
commit
f7bfa13144
4 changed files with 178 additions and 0 deletions
0
mibuild/lattice/__init__.py
Normal file
0
mibuild/lattice/__init__.py
Normal file
93
mibuild/lattice/diamond.py
Normal file
93
mibuild/lattice/diamond.py
Normal file
|
@ -0,0 +1,93 @@
|
|||
# This file is Copyright (c) 2015 Florent Kermarrec <florent@enjoy-digital.fr>
|
||||
# License: BSD
|
||||
|
||||
import os, subprocess, shutil
|
||||
|
||||
from migen.fhdl.structure import _Fragment
|
||||
from mibuild.generic_platform import *
|
||||
from mibuild import tools
|
||||
|
||||
def _format_constraint(c):
|
||||
if isinstance(c, Pins):
|
||||
return ("LOCATE COMP ", " SITE " + "\"" + c.identifiers[0] + "\"")
|
||||
elif isinstance(c, IOStandard):
|
||||
return ("IOBUF PORT ", " IO_TYPE=" + c.name)
|
||||
elif isinstance(c, Misc):
|
||||
return c.misc
|
||||
|
||||
def _format_lpf(signame, pin, others, resname):
|
||||
fmt_c = [_format_constraint(c) for c in ([Pins(pin)] + others)]
|
||||
r = ""
|
||||
for pre, suf in fmt_c:
|
||||
r += pre + "\""+ signame +"\"" + suf + ";\n"
|
||||
return r
|
||||
|
||||
def _build_lpf(named_sc, named_pc):
|
||||
r = "BLOCK RESETPATHS;\n"
|
||||
r += "BLOCK ASYNCPATHS;\n"
|
||||
for sig, pins, others, resname in named_sc:
|
||||
if len(pins) > 1:
|
||||
for i, p in enumerate(pins):
|
||||
r += _format_lpf(sig + "[" + str(i) + "]", p, others, resname)
|
||||
else:
|
||||
r += _format_lpf(sig, pins[0], others, resname)
|
||||
if named_pc:
|
||||
r += "\n" + "\n\n".join(named_pc)
|
||||
return r
|
||||
|
||||
def _build_files(device, sources, vincpaths, build_name):
|
||||
tcl = []
|
||||
tcl.append("prj_project new -name \"%s\" -impl \"implementation\" -dev %s -synthesis \"synplify\"" %(build_name, device))
|
||||
for filename, language in sources:
|
||||
tcl.append("prj_src add \"" + filename.replace("\\", "/") + "\"")
|
||||
tcl.append("prj_run Synthesis -impl implementation -forceOne")
|
||||
tcl.append("prj_run Translate -impl implementation")
|
||||
tcl.append("prj_run Map -impl implementation")
|
||||
tcl.append("prj_run PAR -impl implementation")
|
||||
tcl.append("prj_run Export -impl implementation -task Bitgen")
|
||||
tools.write_to_file(build_name + ".tcl", "\n".join(tcl))
|
||||
|
||||
def _run_diamond(build_name, source, ver=None):
|
||||
if sys.platform == "win32" or sys.platform == "cygwin":
|
||||
build_script_contents = "REM Autogenerated by mibuild\n"
|
||||
build_script_contents = "pnmainc " + build_name + ".tcl\n"
|
||||
build_script_file = "build_" + build_name + ".bat"
|
||||
tools.write_to_file(build_script_file, build_script_contents)
|
||||
r = subprocess.call([build_script_file])
|
||||
shutil.copy(os.path.join("implementation", build_name + "_implementation.bit"), build_name + ".bit")
|
||||
else:
|
||||
raise NotImplementedError()
|
||||
|
||||
if r != 0:
|
||||
raise OSError("Subprocess failed")
|
||||
|
||||
class LatticeDiamondPlatform(GenericPlatform):
|
||||
bitstream_ext = ".bit"
|
||||
def build(self, fragment, build_dir="build", build_name="top",
|
||||
diamond_path="/opt/Diamond", run=True):
|
||||
tools.mkdir_noerror(build_dir)
|
||||
os.chdir(build_dir)
|
||||
|
||||
if not isinstance(fragment, _Fragment):
|
||||
fragment = fragment.get_fragment()
|
||||
self.finalize(fragment)
|
||||
|
||||
v_src, vns = self.get_verilog(fragment)
|
||||
named_sc, named_pc = self.resolve_signals(vns)
|
||||
v_file = build_name + ".v"
|
||||
tools.write_to_file(v_file, v_src)
|
||||
sources = self.sources + [(v_file, "verilog")]
|
||||
_build_files(self.device, sources, self.verilog_include_paths, build_name)
|
||||
|
||||
tools.write_to_file(build_name + ".lpf", _build_lpf(named_sc, named_pc))
|
||||
|
||||
if run:
|
||||
_run_diamond(build_name, diamond_path)
|
||||
|
||||
os.chdir("..")
|
||||
|
||||
return vns
|
||||
|
||||
def add_period_constraint(self, clk, period):
|
||||
# TODO: handle differential clk
|
||||
self.add_platform_command("""FREQUENCY PORT "{clk}" {freq} MHz;""".format(freq=str(float(1/period)*1000), clk="{clk}"), clk=clk)
|
51
mibuild/lattice/programmer.py
Normal file
51
mibuild/lattice/programmer.py
Normal file
|
@ -0,0 +1,51 @@
|
|||
import os, subprocess
|
||||
|
||||
from mibuild.generic_programmer import GenericProgrammer
|
||||
from mibuild import tools
|
||||
|
||||
# XXX Lattice programmer need an .xcf file, will need clean up and support for more parameters
|
||||
_xcf_template = """
|
||||
<?xml version='1.0' encoding='utf-8' ?>
|
||||
<!DOCTYPE ispXCF SYSTEM "IspXCF.dtd" >
|
||||
<ispXCF version="3.4.1">
|
||||
<Comment></Comment>
|
||||
<Chain>
|
||||
<Comm>JTAG</Comm>
|
||||
<Device>
|
||||
<SelectedProg value="TRUE"/>
|
||||
<Pos>1</Pos>
|
||||
<Vendor>Lattice</Vendor>
|
||||
<Family>LatticeECP3</Family>
|
||||
<Name>LFE3-35EA</Name>
|
||||
<File>{bitstream_file}</File>
|
||||
<Operation>Fast Program</Operation>
|
||||
</Device>
|
||||
</Chain>
|
||||
<ProjectOptions>
|
||||
<Program>SEQUENTIAL</Program>
|
||||
<Process>ENTIRED CHAIN</Process>
|
||||
<OperationOverride>No Override</OperationOverride>
|
||||
<StartTAP>TLR</StartTAP>
|
||||
<EndTAP>TLR</EndTAP>
|
||||
<VerifyUsercode value="FALSE"/>
|
||||
</ProjectOptions>
|
||||
<CableOptions>
|
||||
<CableName>USB2</CableName>
|
||||
<PortAdd>FTUSB-0</PortAdd>
|
||||
<USBID>Dual RS232-HS A Location 0000 Serial A</USBID>
|
||||
<JTAGPinSetting>
|
||||
TRST ABSENT;
|
||||
ISPEN ABSENT;
|
||||
</JTAGPinSetting>
|
||||
</CableOptions>
|
||||
</ispXCF>
|
||||
"""
|
||||
|
||||
class LatticeProgrammer(GenericProgrammer):
|
||||
needs_bitreverse = False
|
||||
|
||||
def load_bitstream(self, bitstream_file):
|
||||
xcf_file = bitstream_file.replace(".bit", ".xcf")
|
||||
xcf_content = _xcf_template.format(bitstream_file=bitstream_file)
|
||||
tools.write_to_file(xcf_file, xcf_content)
|
||||
subprocess.call(["pgrcmd", "-infile", xcf_file])
|
34
mibuild/platforms/versa.py
Normal file
34
mibuild/platforms/versa.py
Normal file
|
@ -0,0 +1,34 @@
|
|||
# This file is Copyright (c) 2013 Florent Kermarrec <florent@enjoy-digital.fr>
|
||||
# License: BSD
|
||||
|
||||
from mibuild.generic_platform import *
|
||||
from mibuild.lattice.diamond import LatticeDiamondPlatform
|
||||
from mibuild.lattice.programmer import LatticeProgrammer
|
||||
|
||||
_io = [
|
||||
("clk100", 0, Pins("L5"), IOStandard("LVDS25")),
|
||||
|
||||
("user_led", 0, Pins("Y20"), IOStandard("LVCMOS33")),
|
||||
("user_led", 1, Pins("AA21"), IOStandard("LVCMOS33")),
|
||||
("user_led", 2, Pins("U18"), IOStandard("LVCMOS33")),
|
||||
("user_led", 3, Pins("U19"), IOStandard("LVCMOS33")),
|
||||
("user_led", 4, Pins("W19"), IOStandard("LVCMOS33")),
|
||||
("user_led", 5, Pins("V19"), IOStandard("LVCMOS33")),
|
||||
("user_led", 6, Pins("AB20"), IOStandard("LVCMOS33")),
|
||||
("user_led", 7, Pins("AA20"), IOStandard("LVCMOS33")),
|
||||
|
||||
("serial", 0,
|
||||
Subsignal("tx", Pins("B11"), IOStandard("LVCMOS33")), # X4 IO0
|
||||
Subsignal("rx", Pins("B12"), IOStandard("LVCMOS33")), # X4 IO1
|
||||
),
|
||||
]
|
||||
|
||||
class Platform(LatticeDiamondPlatform):
|
||||
default_clk_name = "clk100"
|
||||
default_clk_period = 10
|
||||
|
||||
def __init__(self):
|
||||
LatticeDiamondPlatform.__init__(self, "LFE3-35EA-6FN484C", _io)
|
||||
|
||||
def create_programmer(self):
|
||||
return LatticeProgrammer()
|
Loading…
Reference in a new issue