Skip to content

Commit

Permalink
Port Modelsim/Questasim backend to flow API
Browse files Browse the repository at this point in the history
  • Loading branch information
olofk committed Aug 22, 2024
1 parent 9696c99 commit fdf1cc1
Show file tree
Hide file tree
Showing 8 changed files with 291 additions and 0 deletions.
208 changes: 208 additions & 0 deletions edalize/tools/modelsim.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
# Copyright edalize contributors
# Licensed under the 2-Clause BSD License, see LICENSE for details.
# SPDX-License-Identifier: BSD-2-Clause

from pathlib import Path

from edalize.tools.edatool import Edatool
from edalize.utils import EdaCommands


class Modelsim(Edatool):

description = "ModelSim/QuestaSim simulator from Siemens EDA"

TOOL_OPTIONS = {
"compilation_mode": {
"type": "str",
"desc": "Common or separate compilation, sep - for separate compilation, common - for common compilation",
},
"vcom_options": {
"type": "str",
"desc": "Additional options for compilation with vcom",
list: True,
},
"vlog_options": {
"type": "str",
"desc": "Additional options for compilation with vlog",
list: True,
},
"vsim_options": {
"type": "str",
"desc": "Additional run options for vsim",
list: True,
},
}

def setup(self, edam):
super().setup(edam)

incdirs = []
vlog_files = []
depfiles = []
unused_files = []
libs = []

vlog_defines = []
for k, v in self.vlogdefine.items():
vlog_defines.append("+define+{}={}".format(k, self._param_value_str(v)))

common_compilation = self.tool_options.get("compilation_mode") == "common"
vlog_options = self.tool_options.get("vlog_options", [])
vcom_options = self.tool_options.get("vcom_options", [])
vsim_options = self.tool_options.get("vsim_options", [])

# Get all include dirs first
for f in self.files:
file_type = f.get("file_type", "")
if file_type.startswith("verilogSource") or file_type.startswith(
"systemVerilogSource"
):
self._add_include_dir(f, incdirs, force_slash=True)

vlog_include_dirs = ["+incdir+" + d.replace("\\", "/") for d in incdirs]

self.tcl_files = []
self.tcl_main = []
self.tcl_build_rtl = []
for f in self.files:
if not f.get("logical_name"):
f["logical_name"] = "work"
if not f["logical_name"] in libs:
self.tcl_build_rtl.append(f"vlib {f['logical_name']}")
libs.append(f["logical_name"])
file_type = f.get("file_type", "")
if file_type.startswith("verilogSource") or file_type.startswith(
"systemVerilogSource"
):
depfiles.append(f["name"])
if self._add_include_dir(f, incdirs, force_slash=True):
cmd = None
else:
vlog_files.append(f)
cmd = "vlog"
args = []

args += vlog_include_dirs
args += vlog_options
args += vlog_defines

if file_type.startswith("systemVerilogSource"):
args += ["-sv"]

elif file_type.startswith("vhdlSource"):
depfiles.append(f["name"])
cmd = "vcom"
if file_type.endswith("-87"):
args = ["-87"]
if file_type.endswith("-93"):
args = ["-93"]
if file_type.endswith("-2008"):
args = ["-2008"]
else:
args = []

args += vcom_options

elif file_type == "tclSource":
depfiles.append(f["name"])
cmd = None
self.tcl_files.append(f["name"])
elif file_type == "user":
depfiles.append(f["name"])
cmd = None
else:
unused_files.append(f)
cmd = None
if cmd and ((cmd != "vlog") or not common_compilation):
args += ["-quiet"]
args += ["-work", f["logical_name"]]
args += [f["name"].replace("\\", "/")]
self.tcl_build_rtl.append(f"{cmd} {' '.join(args)}")

if common_compilation:
args = vlog_include_dirs + vlog_options + vlog_defines
_vlog_files = []
has_sv = False
for f in vlog_files:
_vlog_files.append(f["name"].replace("\\", "/"))
if f.get("file_type", "").startswith("systemVerilogSource"):
has_sv = True

if has_sv:
args += ["-sv"]
args += vlog_include_dirs
args += ["-quiet"]
args += ["-work", "work"]
args += ["-mfcu"]
self.tcl_build_rtl.append(f"vlog {' '.join(args)} {' '.join(_vlog_files)}")

self.edam = edam.copy()
self.edam["files"] = unused_files

self.commands = EdaCommands()

_parameters = []

db_file = str(Path("work") / "_lib.qdb")
self.commands.add(
["vsim"] + ["-c", "-do", '"do edalize_main.tcl; exit"'],
[db_file],
depfiles + ["edalize_main.tcl", "edalize_build_rtl.tcl"],
)

for key, value in self.vlogparam.items():
_parameters += ["-g", "{}={}".format(key, self._param_value_str(value))]
for key, value in self.generic.items():
_parameters += [
"-g",
"{}={}".format(key, self._param_value_str(value, bool_is_str=True)),
]

self.commands.add(
["vsim", "-c"]
+ vsim_options
+ _parameters
+ [
"$(EXTRA_OPTIONS)",
"-do",
'"run -all; quit -code [expr [coverage attribute -name TESTSTATUS -concise] >= 2 ? [coverage attribute -name TESTSTATUS -concise] : 0]; exit"',
self.toplevel,
],
["run"],
[db_file],
)

self.commands.add(
["vsim", "-gui"]
+ vsim_options
+ _parameters
+ ["$(EXTRA_OPTIONS)", self.toplevel],
["run-gui"],
[db_file],
)
self.commands.set_default_target(db_file)

def write_config_files(self):
tcl_main = "onerror { quit -code 1; }\ndo edalize_build_rtl.tcl\n"

for f in self.tcl_files:
tcl_main += f"do {f}\n"

self.update_config_file("edalize_main.tcl", tcl_main)

tcl_build_rtl = "\n".join(self.tcl_build_rtl)

self.update_config_file("edalize_build_rtl.tcl", tcl_build_rtl)

def run(self):
args = ["run"]

# Set plusargs
if self.plusarg:
plusargs = []
for key, value in self.plusarg.items():
plusargs += ["+{}={}".format(key, self._param_value_str(value))]
args.append("EXTRA_OPTIONS=" + " ".join(plusargs))

return ("make", args, self.work_root)
38 changes: 38 additions & 0 deletions tests/test_tool_modelsim.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
from .edalize_tool_common import tool_fixture


def test_tool_modelsim(tool_fixture):
tool_name = "modelsim"

# "compilation_mode": {
# "desc": "Common or separate compilation, sep - for separate compilation, common - for common compilation",
tool_options = {
"vcom_options": ["several", "vcom", "options"],
"vlog_options": ["a", "few", "vlog", "options"],
"vsim_options": ["some", "vsim", "options"],
}
tf = tool_fixture(tool_name, tool_options=tool_options)

tf.tool.configure()
tf.compare_config_files(["edalize_build_rtl.tcl", "edalize_main.tcl"])

tf.tool.run()


def test_tool_modelsim_mfcu(tool_fixture):
tool_name = "modelsim"

# "compilation_mode": {
# "desc": "Common or separate compilation, sep - for separate compilation, common - for common compilation",
tool_options = {
"compilation_mode": "common",
"vcom_options": ["several", "vcom", "options"],
"vlog_options": ["a", "few", "vlog", "options"],
"vsim_options": ["some", "vsim", "options"],
}
tf = tool_fixture(tool_name, tool_options=tool_options, ref_subdir="mfcu")

tf.tool.configure()
tf.compare_config_files(["edalize_build_rtl.tcl", "edalize_main.tcl"])

tf.tool.run()
12 changes: 12 additions & 0 deletions tests/tools/modelsim/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#Auto generated by Edalize

all: work/_lib.qdb

work/_lib.qdb: sv_file.sv user_file tcl_file.tcl vlog_file.v vlog05_file.v vlog_incfile vhdl_file.vhd vhdl_lfile vhdl2008_file another_sv_file.sv edalize_main.tcl edalize_build_rtl.tcl
$(EDALIZE_LAUNCHER) vsim -c -do "do edalize_main.tcl; exit"

run: work/_lib.qdb
$(EDALIZE_LAUNCHER) vsim -c some vsim options -g vlogparam_bool=1 -g vlogparam_int=42 -g vlogparam_str=hello $(EXTRA_OPTIONS) -do "run -all; quit -code [expr [coverage attribute -name TESTSTATUS -concise] >= 2 ? [coverage attribute -name TESTSTATUS -concise] : 0]; exit" top_module

run-gui: work/_lib.qdb
$(EDALIZE_LAUNCHER) vsim -gui some vsim options -g vlogparam_bool=1 -g vlogparam_int=42 -g vlogparam_str=hello $(EXTRA_OPTIONS) top_module
9 changes: 9 additions & 0 deletions tests/tools/modelsim/edalize_build_rtl.tcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
vlib work
vlog +incdir+. a few vlog options +define+vlogdefine_bool=1 +define+vlogdefine_int=42 +define+vlogdefine_str=hello -sv -quiet -work work sv_file.sv
vlog +incdir+. a few vlog options +define+vlogdefine_bool=1 +define+vlogdefine_int=42 +define+vlogdefine_str=hello -quiet -work work vlog_file.v
vlog +incdir+. a few vlog options +define+vlogdefine_bool=1 +define+vlogdefine_int=42 +define+vlogdefine_str=hello -quiet -work work vlog05_file.v
vcom several vcom options -quiet -work work vhdl_file.vhd
vlib libx
vcom several vcom options -quiet -work libx vhdl_lfile
vcom -2008 several vcom options -quiet -work work vhdl2008_file
vlog +incdir+. a few vlog options +define+vlogdefine_bool=1 +define+vlogdefine_int=42 +define+vlogdefine_str=hello -sv -quiet -work work another_sv_file.sv
3 changes: 3 additions & 0 deletions tests/tools/modelsim/edalize_main.tcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
onerror { quit -code 1; }
do edalize_build_rtl.tcl
do tcl_file.tcl
12 changes: 12 additions & 0 deletions tests/tools/modelsim/mfcu/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#Auto generated by Edalize

all: work/_lib.qdb

work/_lib.qdb: sv_file.sv user_file tcl_file.tcl vlog_file.v vlog05_file.v vlog_incfile vhdl_file.vhd vhdl_lfile vhdl2008_file another_sv_file.sv edalize_main.tcl edalize_build_rtl.tcl
$(EDALIZE_LAUNCHER) vsim -c -do "do edalize_main.tcl; exit"

run: work/_lib.qdb
$(EDALIZE_LAUNCHER) vsim -c some vsim options -g vlogparam_bool=1 -g vlogparam_int=42 -g vlogparam_str=hello $(EXTRA_OPTIONS) -do "run -all; quit -code [expr [coverage attribute -name TESTSTATUS -concise] >= 2 ? [coverage attribute -name TESTSTATUS -concise] : 0]; exit" top_module

run-gui: work/_lib.qdb
$(EDALIZE_LAUNCHER) vsim -gui some vsim options -g vlogparam_bool=1 -g vlogparam_int=42 -g vlogparam_str=hello $(EXTRA_OPTIONS) top_module
6 changes: 6 additions & 0 deletions tests/tools/modelsim/mfcu/edalize_build_rtl.tcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
vlib work
vcom several vcom options -quiet -work work vhdl_file.vhd
vlib libx
vcom several vcom options -quiet -work libx vhdl_lfile
vcom -2008 several vcom options -quiet -work work vhdl2008_file
vlog +incdir+. a few vlog options +define+vlogdefine_bool=1 +define+vlogdefine_int=42 +define+vlogdefine_str=hello -sv +incdir+. -quiet -work work -mfcu sv_file.sv vlog_file.v vlog05_file.v another_sv_file.sv
3 changes: 3 additions & 0 deletions tests/tools/modelsim/mfcu/edalize_main.tcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
onerror { quit -code 1; }
do edalize_build_rtl.tcl
do tcl_file.tcl

0 comments on commit fdf1cc1

Please sign in to comment.