Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions doc/edalize.rst
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,14 @@ edalize.ise_reporting module
:members:
:undoc-members:
:show-inheritance:

edalize.design_compiler module
--------------------------------

.. automodule:: edalize.design_compiler
:members:
:undoc-members:
:show-inheritance:

Module contents
---------------
Expand Down
179 changes: 179 additions & 0 deletions edalize/design_compiler.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
# Copyright edalize contributors
# Licensed under the 2-Clause BSD License, see LICENSE for details.
# SPDX-License-Identifier: BSD-2-Clause

import logging
import os.path
import platform
import re
import subprocess

from edalize.edatool import Edatool
from edalize.yosys import Yosys
from importlib import import_module

logger = logging.getLogger(__name__)

""" design-compiler Backend

A core (usually the system core) can add the following files:

- Standard design sources

- Libraries
"""


class Design_compiler(Edatool):

argtypes = ["vlogdefine", "vlogparam", "generic"]

@classmethod
def get_doc(cls, api_ver):
if api_ver == 0:
return {
"description": "The design_compiler backend executes Synopsys design_copiler to build a gate-level netlist",
"members": [
{
"name": "script_dir",
"type": "String",
"desc": "Path to Syopsys scripts (e.g. /home/user/project/synopsys/scripts)",
},
{
"name": "dc_script",
"type": "String",
"desc": "Name of the synthesis script to run [located in script_dir](e.g. synth.tcl)",
},
{
"name": "report_dir",
"type": "String",
"desc": "Path to where reports should be stored (e.g. /home/user/project/synopsys/reports)",
},
{
"name": "target_library",
"type": "String",
"desc": "The Design Compiler target_library",
},
{
"name": "libs",
"type": "String",
"desc": "Libraries to use in the Design Compiler link_library",
},
{
"name": "jobs",
"type": "Integer",
"desc": "Number of jobs. Useful for parallelizing syntheses.",
},
],
}

""" Configuration is the first phase of the build
This writes the project TCL files and Makefile. It first collects all
sources, IPs and constraints and then writes them to the TCL file along
with the build steps.
"""

def configure_main(self):
def make_list(opt):
if opt:
opt = (
((opt.replace("[", "")).replace("]", "")).replace(",", "")
).replace("'", "")
return opt

(src_files, incdirs) = self._get_fileset_files(force_slash=True)

self.jinja_env.filters["src_file_filter"] = self.src_file_filter

self.synth_tool = self.tool_options.get("synth", "design-compiler")

template_vars = {
"name": self.name,
"src_files": src_files,
"incdirs": incdirs + ["."],
"tool_options": self.tool_options,
"script_dir": make_list(self.tool_options.get("script_dir")),
"dc_script": make_list(self.tool_options.get("dc_script")),
"report_dir": make_list(self.tool_options.get("report_dir")),
"target_library": self.tool_options.get("target_library"),
"libs": make_list(self.tool_options.get("libs")),
"toplevel": self.toplevel,
}

design_compiler_settings = self.tool_options.get(
"design_compiler-settings", None
)
design_compiler_command = (
"source {} && design_compiler".format(design_compiler_settings)
if design_compiler_settings
else "design_compiler"
)

self.render_template(
"design-compiler-makefile.j2",
"Makefile",
{
"name": self.name,
"report_dir": make_list(self.tool_options.get("report_dir")),
"design_compiler_command_command": design_compiler_command,
},
)

jobs = self.tool_options.get("jobs", None)

run_template_vars = {"jobs": " -jobs " + str(jobs) if jobs is not None else ""}

self.render_template(
"design-compiler-project.tcl.j2", self.name + ".tcl", template_vars
)

self.render_template(
"design-compiler-read-sources.tcl.j2",
self.name + "-read-sources.tcl",
template_vars,
)

def src_file_filter(self, f):
file_types = {
"verilogSource": "analyze -format verilog",
"systemVerilogSource": "analyze -format sverilog",
"vhdlSource": "analyze -format vhdl",
"tclSource": "source",
"SDC": "source",
}

_file_type = f.file_type.split("-")[0]
if _file_type in file_types:
cmd = ""
cmd += file_types[_file_type] + " "

if (_file_type != "tclSource") and (_file_type != "SDC"):
cmd_define = ""
if (_file_type != "vhdlSource") and (self.vlogdefine.items() != {}):
cmd_define = "-define {"
for k, v in self.vlogdefine.items():
# Skip reddefinition of SYNTHESIS which is a reserved macro in IEEE Verilog synthesizable subset
if k != "SYNTHESIS":
cmd_define += " {}={}".format(k, self._param_value_str(v))
cmd_define += " }"

cmd += cmd_define + " " + "-work work " + f.name
else:
cmd += " " + f.name

return cmd

if _file_type == "user":
return ""

_s = "{} has unknown file type '{}', interpretation is up to Design Compiler"
logger.warning(_s.format(f.name, f.file_type))
return "add_files -norecurse" + " " + f.name

def build_main(self):
logger.info("Building")
logger.info(
"(running make, which runs dc_shell which has an unbelievably long lag before printing. be patient)"
)
args = []
self._run_tool("make", args, quiet=True)
169 changes: 169 additions & 0 deletions edalize/genus.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
# Copyright edalize contributors
# Licensed under the 2-Clause BSD License, see LICENSE for details.
# SPDX-License-Identifier: BSD-2-Clause

import logging
import os.path
import platform
import re
import subprocess

from edalize.edatool import Edatool
from edalize.yosys import Yosys
from importlib import import_module

logger = logging.getLogger(__name__)

""" Cadence Genus Backend

A core (usually the system core) can add the following files:

- Standard design sources

- Libraries
"""


class Genus(Edatool):

argtypes = ["vlogdefine", "vlogparam", "generic"]

@classmethod
def get_doc(cls, api_ver):
if api_ver == 0:
return {
"description": "The genus backend executes cadence genus to build a gate-level netlist",
"members": [
{
"name": "script_dir",
"type": "String",
"desc": "Path to Genus scripts (e.g. /home/user/project/genus/scripts)",
},
{
"name": "genus_script",
"type": "String",
"desc": "Name of the synthesis script to run [located in script_dir](e.g. synth.tcl)",
},
{
"name": "report_dir",
"type": "String",
"desc": "Path to where reports should be stored (e.g. /home/user/project/genus/reports)",
},
{
"name": "common_config",
"type": "String",
"desc": "A TCL file to be sourced, defining common project specific variables shared between genus and innovus (Loction of MMMC view, LEFs, DEFs, UPF, Paths, ...)",
},
{
"name": "jobs",
"type": "String",
"desc": 'Number of jobs. Useful for parallelizing syntheses. Use "all" to set the number of jobs to the number of cores available.',
},
],
}

""" Configuration is the first phase of the build
This writes the project TCL files and Makefile. It first collects all
sources, IPs and constraints and then writes them to the TCL file along
with the build steps.
"""

def configure_main(self):
def make_list(opt):
if opt:
opt = (
((opt.replace("[", "")).replace("]", "")).replace(",", "")
).replace("'", "")
return opt

(src_files, incdirs) = self._get_fileset_files(force_slash=True)

self.jinja_env.filters["src_file_filter"] = self.src_file_filter

self.synth_tool = self.tool_options.get("synth", "genus")

jobs = self.tool_options.get("jobs", None)
jobs = "$nproc" if "all" in jobs else jobs

template_vars = {
"name": self.name,
"src_files": src_files,
"incdirs": incdirs + ["."],
"tool_options": self.tool_options,
"script_dir": make_list(self.tool_options.get("script_dir")),
"genus_script": make_list(self.tool_options.get("genus_script")),
"report_dir": make_list(self.tool_options.get("report_dir")),
"common_config": make_list(self.tool_options.get("common_config")),
"jobs": make_list(jobs),
"toplevel": self.toplevel,
}

genus_settings = self.tool_options.get("genus-settings", None)
genus_command = (
"source {} && genus".format(genus_settings) if genus_settings else "genus"
)

self.render_template(
"genus-makefile.j2",
"Makefile",
{
"name": self.name,
"report_dir": make_list(self.tool_options.get("report_dir")),
"genus_command_command": genus_command,
},
)

self.render_template("genus-project.tcl.j2", self.name + ".tcl", template_vars)

self.render_template(
"genus-read-sources.tcl.j2", self.name + "-read-sources.tcl", template_vars
)

def src_file_filter(self, f):
file_types = {
"verilogSource": "read_hdl -language v2001",
"systemVerilogSource": "read_hdl -language sv",
"vhdlSource": "read_hdl -language vhdl",
"tclSource": "source",
# Note: we do not add an SDC source here as the constraint files are
# referenced inside the MMMC view file on a per corner base
}
_file_type = f.file_type.split("-")[0]

if _file_type in file_types:
cmd = ""
cmd += file_types[_file_type] + " "

if (_file_type != "tclSource") and (_file_type != "SDC"):
cmd_define = ""
if (_file_type != "vhdlSource") and (self.vlogdefine.items() != {}):
cmd_define = "-define {"
for k, v in self.vlogdefine.items():
# Skip reddefinition of SYNTHESIS which is a reserved macro in IEEE Verilog synthesizable subset
if k != "SYNTHESIS":
cmd_define += " {}={}".format(k, self._param_value_str(v))
cmd_define += " }"

cmd += cmd_define + " " + "-library work " + f.name
else:
cmd += " " + f.name

return cmd

if _file_type in file_types:
return file_types[_file_type] + " " + f.name

if _file_type == "user":
return ""

_s = "{} has unknown file type '{}', interpretation is up to Genus"
logger.warning(_s.format(f.name, f.file_type))
return "add_files -norecurse" + " " + f.name

def build_main(self):
logger.info("Building")
logger.info(
"(running make, which runs genus which has an unbelievably long lag before printing. be patient)"
)
args = []
self._run_tool("make", args, quiet=True)
12 changes: 12 additions & 0 deletions edalize/templates/design_compiler/design-compiler-makefile.j2
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
SHELL=/bin/bash
NAME := {{ name }}
{% if report_dir -%}
REPORT_DIR := {{ report_dir }}
{% else %}
REPORT_DIR := "./"
{%- endif %}


all:
mkdir -p ${REPORT_DIR}
dc_shell-t -f ${NAME}.tcl |& tee ${REPORT_DIR}/synth.log
Loading