mirror of
https://github.com/enjoy-digital/litex.git
synced 2025-01-04 09:52:26 -05:00
build/altera: switch to sdc constraints, add add_false_path_constraints method
This commit is contained in:
parent
1275e2f150
commit
017147c623
2 changed files with 40 additions and 10 deletions
|
@ -25,3 +25,10 @@ class AlteraPlatform(GenericPlatform):
|
||||||
if hasattr(clk, "p"):
|
if hasattr(clk, "p"):
|
||||||
clk = clk.p
|
clk = clk.p
|
||||||
self.toolchain.add_period_constraint(self, clk, period)
|
self.toolchain.add_period_constraint(self, clk, period)
|
||||||
|
|
||||||
|
def add_false_path_constraint(self, from_, to):
|
||||||
|
if hasattr(from_, "p"):
|
||||||
|
from_ = from_.p
|
||||||
|
if hasattr(to, "p"):
|
||||||
|
to = to.p
|
||||||
|
self.toolchain.add_false_path_constraint(self, from_, to)
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
# This file is Copyright (c) 2013 Florent Kermarrec <florent@enjoy-digital.fr>
|
# This file is Copyright (c) 2013-2019 Florent Kermarrec <florent@enjoy-digital.fr>
|
||||||
# License: BSD
|
# License: BSD
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
|
import math
|
||||||
|
|
||||||
from migen.fhdl.structure import _Fragment
|
from migen.fhdl.structure import _Fragment
|
||||||
|
|
||||||
|
@ -69,6 +70,22 @@ def _build_qsf(named_sc, named_pc, build_name):
|
||||||
return "\n".join(lines)
|
return "\n".join(lines)
|
||||||
|
|
||||||
|
|
||||||
|
def _build_sdc(clocks, false_paths, vns, build_name):
|
||||||
|
lines = []
|
||||||
|
for clk, period in sorted(clocks.items(), key=lambda x: x[0].duid):
|
||||||
|
lines.append(
|
||||||
|
"create_clock -name {clk} -period ".format(clk=vns.get_name(clk)) + str(period) +
|
||||||
|
" [get_ports {{{clk}}}]".format(clk=vns.get_name(clk)))
|
||||||
|
for from_, to in sorted(false_paths,
|
||||||
|
key=lambda x: (x[0].duid, x[1].duid)):
|
||||||
|
lines.append(
|
||||||
|
"set_false_path "
|
||||||
|
"-from [get_clocks {{{from_}}}] "
|
||||||
|
"-to [get_clocks {{{to}}}]".format(
|
||||||
|
from_=vns.get_name(from_), to=vns.get_name(to)))
|
||||||
|
tools.write_to_file("{}.sdc".format(build_name), "\n".join(lines))
|
||||||
|
|
||||||
|
|
||||||
def _build_files(device, sources, vincpaths, named_sc, named_pc, build_name):
|
def _build_files(device, sources, vincpaths, named_sc, named_pc, build_name):
|
||||||
lines = []
|
lines = []
|
||||||
for filename, language, library in sources:
|
for filename, language, library in sources:
|
||||||
|
@ -82,6 +99,7 @@ def _build_files(device, sources, vincpaths, named_sc, named_pc, build_name):
|
||||||
lang=language.upper(),
|
lang=language.upper(),
|
||||||
path=filename.replace("\\", "/"),
|
path=filename.replace("\\", "/"),
|
||||||
lib=library))
|
lib=library))
|
||||||
|
lines.append("set_global_assignment -name SDC_FILE {}.sdc".format(build_name))
|
||||||
|
|
||||||
for path in vincpaths:
|
for path in vincpaths:
|
||||||
lines.append("set_global_assignment -name SEARCH_PATH {}".format(
|
lines.append("set_global_assignment -name SEARCH_PATH {}".format(
|
||||||
|
@ -117,6 +135,10 @@ fi
|
||||||
|
|
||||||
|
|
||||||
class AlteraQuartusToolchain:
|
class AlteraQuartusToolchain:
|
||||||
|
def __init__(self):
|
||||||
|
self.clocks = dict()
|
||||||
|
self.false_paths = set()
|
||||||
|
|
||||||
def build(self, platform, fragment, build_dir="build", build_name="top",
|
def build(self, platform, fragment, build_dir="build", build_name="top",
|
||||||
toolchain_path=None, run=True, **kwargs):
|
toolchain_path=None, run=True, **kwargs):
|
||||||
if toolchain_path is None:
|
if toolchain_path is None:
|
||||||
|
@ -140,6 +162,8 @@ class AlteraQuartusToolchain:
|
||||||
named_sc,
|
named_sc,
|
||||||
named_pc,
|
named_pc,
|
||||||
build_name)
|
build_name)
|
||||||
|
|
||||||
|
_build_sdc(self.clocks, self.false_paths, v_output.ns, build_name)
|
||||||
if run:
|
if run:
|
||||||
_run_quartus(build_name, toolchain_path)
|
_run_quartus(build_name, toolchain_path)
|
||||||
|
|
||||||
|
@ -148,12 +172,11 @@ class AlteraQuartusToolchain:
|
||||||
return v_output.ns
|
return v_output.ns
|
||||||
|
|
||||||
def add_period_constraint(self, platform, clk, period):
|
def add_period_constraint(self, platform, clk, period):
|
||||||
# TODO: handle differential clk
|
if clk in self.clocks:
|
||||||
platform.add_platform_command(
|
raise ValueError("A period constraint already exists")
|
||||||
"set_global_assignment -name duty_cycle 50 -section_id {clk}",
|
period = math.floor(period*1e3)/1e3 # round to lowest picosecond
|
||||||
clk=clk)
|
self.clocks[clk] = period
|
||||||
platform.add_platform_command(
|
|
||||||
"set_global_assignment -name fmax_requirement \"{freq} MHz\" "
|
def add_false_path_constraint(self, platform, from_, to):
|
||||||
"-section_id {clk}".format(freq=(1. / period) * 1000,
|
if (to, from_) not in self.false_paths:
|
||||||
clk="{clk}"),
|
self.false_paths.add((from_, to))
|
||||||
clk=clk)
|
|
||||||
|
|
Loading…
Reference in a new issue