build/lattice/prjtrellis: generate iowrapper to set constraints and TRELLIS_IO
PrjTrellis does not yet have constraint files support, constraints are set with signal attributes and specific TRELLIS_IO instances are requested. This iowrapper does this work for us automatically. Remove this code and replace with a constraint file generation code when PrjTrellis will have constraint file support.
This commit is contained in:
parent
c506c9752c
commit
27ec2a59e2
|
@ -10,6 +10,11 @@ from litex.build.generic_platform import *
|
||||||
from litex.build import tools
|
from litex.build import tools
|
||||||
from litex.build.lattice import common
|
from litex.build.lattice import common
|
||||||
|
|
||||||
|
# TODO:
|
||||||
|
# - add inout support to iowrapper
|
||||||
|
# - verify iowrapper handle correctly multi-bit signals
|
||||||
|
# - check/document attr_translate
|
||||||
|
|
||||||
|
|
||||||
nextpnr_ecp5_architectures = {
|
nextpnr_ecp5_architectures = {
|
||||||
"lfe5u-25f": "25k",
|
"lfe5u-25f": "25k",
|
||||||
|
@ -24,6 +29,87 @@ nextpnr_ecp5_architectures = {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def yosys_import_sources(platform):
|
||||||
|
includes = ""
|
||||||
|
reads = []
|
||||||
|
for path in platform.verilog_include_paths:
|
||||||
|
includes += " -I" + path
|
||||||
|
for filename, language, library in platform.sources:
|
||||||
|
reads.append("read_{}{} {}".format(
|
||||||
|
language, includes, filename))
|
||||||
|
return "\n".join(reads)
|
||||||
|
|
||||||
|
|
||||||
|
def generate_prjtrellis_iowrapper(platform, vns):
|
||||||
|
ios, _ = platform.resolve_signals(vns)
|
||||||
|
ios_direction = {}
|
||||||
|
# resolve ios directions
|
||||||
|
cm = platform.constraint_manager
|
||||||
|
for io_name, io_pin, _, _ in ios:
|
||||||
|
for cm_sig, cm_pin, _, _ in cm.get_sig_constraints():
|
||||||
|
if io_pin == cm_pin:
|
||||||
|
ios_direction[io_name] = cm_sig.direction
|
||||||
|
last_io_name = io_name
|
||||||
|
|
||||||
|
iowrapper_contents = []
|
||||||
|
iowrapper_contents.append("module {build_name}_iowrapper(")
|
||||||
|
|
||||||
|
# ios declaration
|
||||||
|
ios_declaration = ""
|
||||||
|
for io_name, io_pin, _, _ in ios:
|
||||||
|
ios_declaration += "\t" + ios_direction[io_name] + " "
|
||||||
|
if len(io_pin) > 1:
|
||||||
|
ios_declaration += "[{}:0] ".format(len(io_pin - 1))
|
||||||
|
ios_declaration += io_name + "_io"
|
||||||
|
ios_declaration += ",\n" if io_name != last_io_name else ""
|
||||||
|
iowrapper_contents.append(ios_declaration)
|
||||||
|
iowrapper_contents.append(");\n")
|
||||||
|
|
||||||
|
# wires declaration
|
||||||
|
wires_declaration = ""
|
||||||
|
for io_name, io_pin, _, _ in ios:
|
||||||
|
wires_declaration += "wire "
|
||||||
|
if len(io_pin) > 1:
|
||||||
|
wires_declaration += "[{}:0] ".format(len(io_pin - 1))
|
||||||
|
wires_declaration += io_name
|
||||||
|
wires_declaration += ";\n"
|
||||||
|
iowrapper_contents.append(wires_declaration)
|
||||||
|
|
||||||
|
# trellis_io declaration
|
||||||
|
trellis_io_declaration = ""
|
||||||
|
for io_name, io_pin, io_others, _ in ios:
|
||||||
|
for io_other in io_others:
|
||||||
|
if isinstance(io_other, IOStandard):
|
||||||
|
io_standard = io_other.name
|
||||||
|
trellis_io_declaration += \
|
||||||
|
"(* LOC=\"{}\" *) (* IO_TYPE=\"{}\" *)\n".format(io_pin[0], io_standard)
|
||||||
|
if ios_direction[io_name] == "input":
|
||||||
|
trellis_io_declaration += \
|
||||||
|
"TRELLIS_IO #(.DIR(\"INPUT\")) {} (.B({}), .O({}));\n".format(
|
||||||
|
io_name + "_buf", io_name + "_io", io_name)
|
||||||
|
elif ios_direction[io_name] == "output":
|
||||||
|
trellis_io_declaration += \
|
||||||
|
"TRELLIS_IO #(.DIR(\"OUTPUT\")) {} (.B({}), .I({}));\n".format(
|
||||||
|
io_name + "_buf", io_name + "_io", io_name)
|
||||||
|
else:
|
||||||
|
raise NotImplementedError
|
||||||
|
iowrapper_contents.append(trellis_io_declaration)
|
||||||
|
|
||||||
|
# top declaration
|
||||||
|
top_declaration = "{build_name} _{build_name}(\n"
|
||||||
|
for io_name, io_pin, _, _ in ios:
|
||||||
|
top_declaration += "\t." + io_name + "(" + io_name + ")"
|
||||||
|
top_declaration += ",\n" if io_name != last_io_name else "\n"
|
||||||
|
top_declaration += ");\n"
|
||||||
|
iowrapper_contents.append(top_declaration)
|
||||||
|
|
||||||
|
iowrapper_contents.append("endmodule")
|
||||||
|
|
||||||
|
iowrapper_contents = "\n".join(iowrapper_contents)
|
||||||
|
|
||||||
|
return iowrapper_contents
|
||||||
|
|
||||||
|
|
||||||
class LatticePrjTrellisToolchain:
|
class LatticePrjTrellisToolchain:
|
||||||
attr_translate = {
|
attr_translate = {
|
||||||
# FIXME: document
|
# FIXME: document
|
||||||
|
@ -52,26 +138,23 @@ class LatticePrjTrellisToolchain:
|
||||||
platform.finalize(fragment)
|
platform.finalize(fragment)
|
||||||
|
|
||||||
v_output = platform.get_verilog(fragment)
|
v_output = platform.get_verilog(fragment)
|
||||||
named_sc, named_pc = platform.resolve_signals(v_output.ns)
|
|
||||||
v_file = build_name + ".v"
|
v_file = build_name + ".v"
|
||||||
v_output.write(v_file)
|
v_output.write(v_file)
|
||||||
platform.add_source(v_file)
|
platform.add_source(v_file)
|
||||||
|
|
||||||
# generate yosys script
|
# generate iowrapper (with constraints and trellis_ios)
|
||||||
def yosys_import_sources(platform):
|
# FIXME: remove when prjtrellis will support constraint files
|
||||||
includes = ""
|
iowrapper_file = build_name + "_iowrapper.v"
|
||||||
reads = []
|
iowrapper_contents = generate_prjtrellis_iowrapper(platform, v_output.ns)
|
||||||
for path in platform.verilog_include_paths:
|
iowrapper_contents = iowrapper_contents.format(build_name=build_name)
|
||||||
includes += " -I" + path
|
tools.write_to_file(iowrapper_file, iowrapper_contents)
|
||||||
for filename, language, library in platform.sources:
|
platform.add_source(iowrapper_file)
|
||||||
reads.append("read_{}{} {}".format(
|
|
||||||
language, includes, filename))
|
|
||||||
return "\n".join(reads)
|
|
||||||
|
|
||||||
|
# generate yosys script
|
||||||
yosys_script_file = build_name + ".ys"
|
yosys_script_file = build_name + ".ys"
|
||||||
yosys_script_contents = [
|
yosys_script_contents = [
|
||||||
yosys_import_sources(platform),
|
yosys_import_sources(platform),
|
||||||
"synth_ecp5 -nomux -json {build_name}.json -top {build_name}"
|
"synth_ecp5 -nomux -json {build_name}.json -top {build_name}_iowrapper"
|
||||||
]
|
]
|
||||||
yosys_script_contents = "\n".join(yosys_script_contents)
|
yosys_script_contents = "\n".join(yosys_script_contents)
|
||||||
yosys_script_contents = yosys_script_contents.format(build_name=build_name)
|
yosys_script_contents = yosys_script_contents.format(build_name=build_name)
|
||||||
|
|
Loading…
Reference in New Issue