build/gowin: Add initial timing constraints support.

This commit is contained in:
Florent Kermarrec 2021-07-15 11:06:03 +02:00
parent 10ea45da55
commit 730b57d9cd
2 changed files with 37 additions and 4 deletions

View File

@ -6,6 +6,7 @@
# SPDX-License-Identifier: BSD-2-Clause
import os
import math
import subprocess
from shutil import which
@ -14,7 +15,7 @@ from migen.fhdl.structure import _Fragment
from litex.build.generic_platform import *
from litex.build import tools
# IO Constraints (.cst) ----------------------------------------------------------------------------
# Constraints (.cst and .tcl) ----------------------------------------------------------------------
def _build_cst(named_sc, named_pc):
cst = []
@ -43,6 +44,13 @@ def _build_cst(named_sc, named_pc):
with open("top.cst", "w") as f:
f.write("\n".join(cst))
def _build_sdc(clocks, vns):
sdc = []
for clk, period in sorted(clocks.items(), key=lambda x: x[0].duid):
sdc.append(f"create_clock -name {vns.get_name(clk)} -period {str(period)} [get_ports {{{vns.get_name(clk)}}}]")
with open("top.sdc", "w") as f:
f.write("\n".join(sdc))
# Script -------------------------------------------------------------------------------------------
def _build_tcl(name, partnumber, files, options):
@ -51,9 +59,12 @@ def _build_tcl(name, partnumber, files, options):
# Set Device.
tcl.append(f"set_device -name {name} {partnumber}")
# Add IO Constraints.
# Add IOs Constraints.
tcl.append("add_file top.cst")
# Add Timings Constraints.
tcl.append("add_file top.sdc")
# Add Sources.
for f, typ, lib in files:
tcl.append(f"add_file {f}")
@ -76,6 +87,7 @@ class GowinToolchain:
def __init__(self):
self.options = {}
self.clocks = dict()
def build(self, platform, fragment,
build_dir = "build",
@ -103,10 +115,18 @@ class GowinToolchain:
if platform.verilog_include_paths:
self.options["include_path"] = "{" + ";".join(platform.verilog_include_paths) + "}"
# Generate constraints file (.cst)
# Generate constraints file.
# IOs (.cst).
_build_cst(
named_sc = named_sc,
named_pc = named_pc)
named_pc = named_pc
)
# Timings (.sdc)
_build_sdc(
clocks = self.clocks,
vns = v_output.ns
)
# Generate build script (.tcl)
script = _build_tcl(
@ -128,3 +148,12 @@ class GowinToolchain:
os.chdir(cwd)
return v_output.ns
def add_period_constraint(self, platform, clk, period):
clk.attr.add("keep")
period = math.floor(period*1e3)/1e3 # round to lowest picosecond
if clk in self.clocks:
if period != self.clocks[clk]:
raise ValueError("Clock already constrained to {:.2f}ns, new constraint to {:.2f}ns"
.format(self.clocks[clk], period))
self.clocks[clk] = period

View File

@ -39,3 +39,7 @@ class GowinPlatform(GenericPlatform):
def build(self, *args, **kwargs):
return self.toolchain.build(self, *args, **kwargs)
def add_period_constraint(self, clk, period):
if clk is None: return
self.toolchain.add_period_constraint(self, clk, period)