Skip to content

Commit 97b4aa0

Browse files
committed
Add support for Xcelium
Signed-off-by: Daniel Keller <daniel.kellermartinez@csem.ch>
1 parent 4bab23a commit 97b4aa0

2 files changed

Lines changed: 127 additions & 1 deletion

File tree

src/cmd/script.rs

Lines changed: 100 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ pub fn new() -> Command {
4646
.value_parser([
4747
PossibleValue::new("flist"),
4848
PossibleValue::new("flist-plus"),
49+
PossibleValue::new("xcelium"),
4950
PossibleValue::new("vsim"),
5051
PossibleValue::new("vcs"),
5152
PossibleValue::new("verilator"),
@@ -92,6 +93,15 @@ pub fn new() -> Command {
9293
.action(ArgAction::Append)
9394
.value_parser(value_parser!(String)),
9495
)
96+
.arg(
97+
Arg::new("incdir")
98+
.short('I')
99+
.long("incdir")
100+
.help("Add an include directory (repeatable)")
101+
.num_args(1..)
102+
.action(ArgAction::Append)
103+
.value_parser(value_parser!(String)),
104+
)
95105
.arg(
96106
Arg::new("only-defines")
97107
.long("only-defines")
@@ -217,6 +227,7 @@ pub fn run(sess: &Session, matches: &ArgMatches) -> Result<()> {
217227
match format.as_str() {
218228
"flist" => vec!["flist"],
219229
"flist-plus" => vec!["flist"],
230+
"xcelium" => vec!["xcelium", "simulation"],
220231
"vsim" => vec!["vsim", "simulation"],
221232
"vcs" => vec!["vcs", "simulation"],
222233
"verilator" => vec!["verilator", "synthesis"],
@@ -342,6 +353,13 @@ pub fn run(sess: &Session, matches: &ArgMatches) -> Result<()> {
342353
targets,
343354
srcs,
344355
),
356+
"xcelium" => emit_template(
357+
sess,
358+
include_str!("../script_fmt/xcelium_f.tera"),
359+
matches,
360+
targets,
361+
srcs,
362+
),
345363
"vsim" => emit_template(
346364
sess,
347365
include_str!("../script_fmt/vsim_tcl.tera"),
@@ -496,6 +514,7 @@ fn emit_template(
496514
let mut tera_context = Context::new();
497515
tera_context.insert("HEADER_AUTOGEN", HEADER_AUTOGEN);
498516
tera_context.insert("root", sess.root);
517+
tera_context.insert("root_package", &sess.manifest.package.name);
499518
// tera_context.insert("srcs", &srcs);
500519
tera_context.insert("abort_on_error", &!matches.get_flag("no-abort-on-error"));
501520

@@ -537,11 +556,21 @@ fn emit_template(
537556
tera_context.insert("all_defines", &all_defines);
538557

539558
all_incdirs.sort();
559+
// user-provided include dirs
560+
let user_incdirs: IndexSet<PathBuf> = if let Some(dirs) = matches.get_many::<String>("incdir") {
561+
dirs.map(|d| PathBuf::from(d)).collect()
562+
} else {
563+
IndexSet::new()
564+
};
540565
let all_incdirs: IndexSet<PathBuf> = if (!matches.get_flag("only-defines")
541566
&& !matches.get_flag("only-sources"))
542567
|| matches.get_flag("only-includes")
543568
{
544-
all_incdirs.into_iter().map(|p| p.to_path_buf()).collect()
569+
all_incdirs
570+
.into_iter()
571+
.map(|p| p.to_path_buf())
572+
.chain(user_incdirs)
573+
.collect()
545574
} else {
546575
IndexSet::new()
547576
};
@@ -562,6 +591,76 @@ fn emit_template(
562591
};
563592
tera_context.insert("all_files", &all_files);
564593

594+
// Compute per-package files and root files, plus per-package incdirs/defines
595+
#[derive(Debug, Serialize)]
596+
struct TplLib {
597+
name: String,
598+
incdirs: IndexSet<PathBuf>,
599+
defines: IndexSet<(String, Option<String>)>,
600+
files: IndexSet<PathBuf>,
601+
}
602+
603+
let mut libs: IndexMap<String, TplLib> = IndexMap::new();
604+
let mut root_files_map: IndexSet<PathBuf> = IndexSet::new();
605+
for src in &srcs {
606+
// Gather common per-group data
607+
let incdirs: IndexSet<PathBuf> = src
608+
.clone()
609+
.get_incdirs()
610+
.into_iter()
611+
.map(|p| p.to_path_buf())
612+
.collect();
613+
let mut defines: IndexSet<(String, Option<String>)> = IndexMap::new().into_iter().collect();
614+
defines.extend(
615+
src.defines
616+
.iter()
617+
.map(|(k, &v)| (k.to_string(), v.map(String::from))),
618+
);
619+
defines.extend(target_defines.clone().into_iter().collect::<IndexSet<_>>());
620+
// Add user-provided defines
621+
{
622+
let mut dmap = IndexMap::new();
623+
add_defines_from_matches(&mut dmap, matches);
624+
defines.extend(dmap.into_iter().collect::<IndexSet<_>>());
625+
}
626+
627+
if let Some(pkg) = src.package {
628+
if pkg == sess.manifest.package.name {
629+
// Root package: collect files only
630+
for file in &src.files {
631+
if let SourceFile::File(p) = file {
632+
root_files_map.insert(p.to_path_buf());
633+
}
634+
}
635+
} else {
636+
let entry = libs.entry(pkg.to_string()).or_insert_with(|| TplLib {
637+
name: pkg.to_string(),
638+
incdirs: IndexSet::new(),
639+
defines: IndexSet::new(),
640+
files: IndexSet::new(),
641+
});
642+
entry.incdirs.extend(incdirs);
643+
entry.defines.extend(defines);
644+
for file in &src.files {
645+
if let SourceFile::File(p) = file {
646+
entry.files.insert(p.to_path_buf());
647+
}
648+
}
649+
}
650+
} else {
651+
// No package: treat as root files
652+
for file in &src.files {
653+
if let SourceFile::File(p) = file {
654+
root_files_map.insert(p.to_path_buf());
655+
}
656+
}
657+
}
658+
}
659+
// libs in stable order
660+
let libs: Vec<TplLib> = libs.into_iter().map(|(_, v)| v).collect();
661+
tera_context.insert("libs", &libs);
662+
tera_context.insert("root_files", &root_files_map);
663+
565664
let mut split_srcs = vec![];
566665
for src in srcs {
567666
separate_files_in_group(

src/script_fmt/xcelium_f.tera

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# {{ HEADER_AUTOGEN }}
2+
{%- for incdir in all_incdirs %}
3+
+incdir+{% if relativize_path and incdir is starting_with(root) %}{{ incdir | replace(from=root, to='$ROOT') }}{% else %}{{ incdir }}{% endif %}
4+
{%- endfor %}
5+
{%- for define in all_defines %}
6+
+define+{{ define.0 }}{% if define.1 %}={{ define.1 }}{% endif %}
7+
{%- endfor %}
8+
{% for lib in libs %}
9+
{#- Sanitize library name for Xcelium (avoid hyphens) -#}
10+
{% set safe_lib_name = lib.name | replace(from="-", to="_") %}
11+
# Library: {{ safe_lib_name }}
12+
-makelib {{ safe_lib_name }}
13+
{%- for incdir in lib.incdirs %}
14+
+incdir+{% if relativize_path and incdir is starting_with(root) %}{{ incdir | replace(from=root, to='$ROOT') }}{% else %}{{ incdir }}{% endif %}
15+
{%- endfor %}
16+
{%- for define in lib.defines %}
17+
+define+{{ define.0 }}{% if define.1 %}={{ define.1 }}{% endif %}
18+
{%- endfor %}
19+
{%- for file in lib.files %}
20+
{% if relativize_path and file is starting_with(root) %}{{ file | replace(from=root, to='$ROOT') }}{% else %}{{ file }}{% endif %}
21+
{%- endfor %}
22+
-endlib
23+
{% endfor %}
24+
25+
{%- for file in root_files %}
26+
{% if relativize_path and file is starting_with(root) %}{{ file | replace(from=root, to='$ROOT') }}{% else %}{{ file }}{% endif %}
27+
{%- endfor -%}

0 commit comments

Comments
 (0)