-
Notifications
You must be signed in to change notification settings - Fork 210
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
mibuild: add initial Lattice Diamond support (with ECP3 Versa board p…
…latform skeleton)
1 parent
beeaefc
commit f7bfa13
Showing
4 changed files
with
178 additions
and
0 deletions.
There are no files selected for viewing
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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]) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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() |