blob: b36ec807a51114ea5f7770de6f062b1c290dd5ad [file] [log] [blame]
# Copyright 2024 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Bazel functions for VCS."""
load("@rules_hdl//verilog:providers.bzl", "VerilogInfo")
def _collect_verilog_files(dep):
transitive_srcs = depset([], transitive = [dep[VerilogInfo].dag])
all_srcs = [verilog_info_struct.srcs
for verilog_info_struct in transitive_srcs.to_list()]
all_files = [src for sub_tuple in all_srcs for src in sub_tuple]
return all_files
def _vcs_testbench_test_impl(ctx):
all_files = _collect_verilog_files(ctx.attr.deps)
vcs_binary_output = ctx.actions.declare_file(ctx.attr.module)
vcs_daidir_output = ctx.actions.declare_directory(
ctx.attr.module + ".daidir")
verilog_files = []
for file in all_files:
if file.extension in ["dat", "mem"]:
continue
verilog_files.append(file)
command = [
"vcs",
"-full64",
"-sverilog",
]
verilog_dirs = dict()
for file in verilog_files:
verilog_dirs[file.dirname] = None
for verilog_file in verilog_files:
command.append(verilog_file.path)
command.append("-o")
command.append(vcs_binary_output.path)
ctx.actions.run_shell(
outputs=[vcs_binary_output, vcs_daidir_output],
inputs=verilog_files,
command = " ".join(command),
use_default_shell_env = True,
)
return [DefaultInfo(runfiles=ctx.runfiles(files=[vcs_daidir_output]),
executable=vcs_binary_output)]
_vcs_testbench_test = rule(
_vcs_testbench_test_impl,
attrs = {
"srcs": attr.label_list(allow_files = True),
"deps": attr.label(
doc = "The verilog target to create a test bench for.",
providers = [VerilogInfo],
mandatory = True,
),
"module": attr.string(
doc = "The name of the verilog module to verilate.",
mandatory = True,
),
},
test = True,
)
def vcs_testbench_test(name, tags=[], **kwargs):
_vcs_testbench_test(name = name, tags = ["vcs"] + tags, **kwargs)
def _vcs_systemc_binary_impl(ctx):
verilog_files = []
for dep in ctx.attr.verilog_deps:
verilog_files += _collect_verilog_files(dep)
systemc_include_paths = []
systemc_link_args = []
libs = []
for dep in ctx.attr.systemc_deps:
transitive_quote_includes = depset([], transitive = [dep[CcInfo].compilation_context.quote_includes])
transitive_system_includes = depset([], transitive = [dep[CcInfo].compilation_context.system_includes])
for include in transitive_quote_includes.to_list():
if include.find('accellera_systemc') == -1:
systemc_include_paths += ["-cflags", "-I" + include]
for include in transitive_system_includes.to_list():
if include.find('accellera_systemc') == -1:
systemc_include_paths += ["-cflags", "-I" + include]
transitive_linker_inputs = depset([], transitive = [dep[CcInfo].linking_context.linker_inputs])
for link in transitive_linker_inputs.to_list():
for library in link.libraries:
if library.pic_static_library:
if library.pic_static_library.path.find('accellera_systemc') == -1:
libs.append(library.pic_static_library)
elif library.static_library:
if library.static_library.path.find('accellera_systemc') == -1:
libs.append(library.static_library)
if library.pic_objects:
for object in library.pic_objects:
systemc_link_args.append(object.path)
vcs_binary_output = ctx.actions.declare_file(ctx.attr.name)
vlogan_command = [
"vlogan",
"-kdb",
"-full64",
"-sverilog",
"-sysc",
"-q",
"-incr_vlogan",
"+define+SIMULATION",
]
vlogan_outputs = []
verilog_files += ctx.files.verilog_srcs
verilog_include_paths = []
for f in verilog_files:
verilog_include_paths += ["-cflags", "-I" + f.dirname]
for (i, file) in enumerate(verilog_files):
vlogan_output = ctx.actions.declare_file(file.path + ".stamp")
vlogan_outputs.append(vlogan_output)
main_module_args = []
if file.basename.startswith(ctx.attr.module):
main_module_args += ["-sc_model", ctx.attr.module]
if file.basename.startswith(ctx.attr.module) and ctx.attr.portmap:
main_module_args += ["-sc_portmap", ctx.file.portmap.path]
prev_input = [vlogan_outputs[i-1]] if i > 0 else []
ctx.actions.run_shell(
command = " ".join(
vlogan_command +
main_module_args +
[file.path, "&&", "touch", vlogan_output.path]
),
outputs = [vlogan_output],
inputs = [file] + prev_input,
use_default_shell_env = True,
progress_message = "[VLOGAN] %{input}",
)
syscan_command = [
"syscan",
"-cflags",
"-g",
"-full64",
"-q",
] + verilog_include_paths + systemc_include_paths
syscan_outputs = []
for (i, file) in enumerate(ctx.files.systemc_srcs):
syscan_output = ctx.actions.declare_file(file.path + ".stamp")
syscan_outputs.append(syscan_output)
prev_input = [syscan_outputs[i-1]] if i > 0 else [vlogan_outputs[-1]]
ctx.actions.run_shell(
command = " ".join(
syscan_command + [file.path, "&&", "touch", syscan_output.path]
),
inputs = vlogan_outputs + prev_input + [file],
outputs = [syscan_output],
use_default_shell_env = True,
progress_message = "[SYSCAN] %{input}",
)
vcs_daidir_output = ctx.actions.declare_directory(
ctx.attr.name + ".daidir")
vcs_vdb_output = ctx.actions.declare_directory(
ctx.attr.name + ".vdb")
vcs_command = [
"vcs",
"-full64",
"-sverilog",
"-q",
"-cflags", "-g",
"-sysc=incr",
"-kdb",
"+vcs+fsdbon",
"-debug_access+all",
"+notimingcheck",
"-timescale=1ns/1ps",
"-cm", "line+tgl+fsm+cond+branch+assert",
"sc_main",
"-o",
vcs_binary_output.path,
] + systemc_link_args
ctx.actions.run_shell(
command = " ".join(vcs_command),
inputs = libs + vlogan_outputs + syscan_outputs,
outputs = [vcs_binary_output, vcs_daidir_output, vcs_vdb_output],
use_default_shell_env = True,
)
return [DefaultInfo(
files=depset([vcs_binary_output]),
runfiles=ctx.runfiles(files=[vcs_daidir_output, vcs_vdb_output]),
executable=vcs_binary_output,
)]
_vcs_systemc_binary = rule(
_vcs_systemc_binary_impl,
attrs = {
"verilog_srcs": attr.label_list(allow_files = True),
"systemc_srcs": attr.label_list(allow_files = True),
"verilog_deps": attr.label_list(
doc = "Verilog library dependencies",
providers = [VerilogInfo],
),
"systemc_deps": attr.label_list(
doc = "SystemC library dependencies",
providers = [CcInfo],
),
"portmap": attr.label(allow_single_file = True),
"module": attr.string(
doc = "The name of the main verilog module.",
mandatory = True,
),
"_cc_toolchain": attr.label(
doc = "CC compiler.",
default = Label("@bazel_tools//tools/cpp:current_cc_toolchain"),
),
},
toolchains = [
"@bazel_tools//tools/cpp:toolchain_type",
],
executable = True,
)
def vcs_systemc_binary(name, tags=[], **kwargs):
_vcs_systemc_binary(name = name, tags = ["vcs"] + tags, **kwargs)