Skip to content

Commit 7840c53

Browse files
authored
Merge pull request #272 from pulp-platform/fischeti/slang-test
Add testing infrastructure for slang
2 parents 1f27025 + af93ecb commit 7840c53

21 files changed

Lines changed: 490 additions & 9 deletions

File tree

.clang-format

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
---
2+
Language: Cpp
3+
BasedOnStyle: LLVM
4+
5+
# 4 spaces everywhere
6+
IndentWidth: 4
7+
TabWidth: 4
8+
UseTab: Never
9+
ContinuationIndentWidth: 4
10+
11+
# Modern C++ style
12+
Standard: c++20
13+
ColumnLimit: 120
14+
PointerAlignment: Left
15+
16+
# Organize includes
17+
SortIncludes: true
18+
IncludeBlocks: Regroup

.clangd

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
If:
2+
PathMatch: (^|.*/)crates/bender-slang/cpp/.*\.(h|hpp|hh|c|cc|cpp|cxx)$
3+
CompileFlags:
4+
Add:
5+
- -std=c++20
6+
- -fno-cxx-modules
7+
- -I.
8+
- -I../../../crates
9+
- -I../vendor/slang/include
10+
- -I../vendor/slang/external
11+
- -I../../../target/slang-generated-include
12+
- -I../../../target/cxxbridge
13+
- -DSLANG_USE_MIMALLOC=1
14+
- -DSLANG_USE_THREADS=1
15+
- -DSLANG_BOOST_SINGLE_HEADER=1

.github/workflows/ci.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ on:
44
push:
55
branches: [master]
66
pull_request:
7-
branches: [master]
87
workflow_dispatch:
98

109
jobs:

.gitignore

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
1-
.*
2-
!/.ci/
3-
!.git*
4-
!.travis.yml
5-
/target
6-
/tests/tmp
1+
# Cargo build files
2+
target
3+
4+
# Temporary test files
5+
tests/**/tmp
6+
tests/**/.bender
7+
8+
# clangd
9+
.cache/clangd

crates/bender-slang/build.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,37 @@
11
// Copyright (c) 2025 ETH Zurich
22
// Tim Fischer <fischeti@iis.ee.ethz.ch>
33

4+
#[cfg(unix)]
5+
// We create a symlink from the generated include directory to a stable location in the target directory
6+
// so that tools like clangd can find the headers without needing to know the exact OUT_DIR path.
7+
// This is purely for improving the development experience and is not necessary for the build itself.
8+
fn refresh_include_symlink(generated_include_dir: &std::path::Path) {
9+
use std::ffi::OsStr;
10+
use std::fs;
11+
use std::os::unix::fs::symlink;
12+
use std::path::PathBuf;
13+
14+
let Ok(out_dir) = std::env::var("OUT_DIR") else {
15+
return;
16+
};
17+
let out_dir = PathBuf::from(out_dir);
18+
19+
let Some(target_root) = out_dir
20+
.ancestors()
21+
.find(|path| path.file_name() == Some(OsStr::new("target")))
22+
else {
23+
return;
24+
};
25+
26+
let stable_link = target_root.join("slang-generated-include");
27+
let _ = fs::remove_file(&stable_link);
28+
let _ = fs::remove_dir_all(&stable_link);
29+
let _ = symlink(generated_include_dir, &stable_link);
30+
}
31+
32+
#[cfg(not(unix))]
33+
fn refresh_include_symlink(_generated_include_dir: &std::path::Path) {}
34+
435
fn main() {
536
let target_os = std::env::var("CARGO_CFG_TARGET_OS").unwrap();
637
let target_env = std::env::var("CARGO_CFG_TARGET_ENV").unwrap();
@@ -64,6 +95,9 @@ fn main() {
6495
let dst = slang_lib.build();
6596
let lib_dir = dst.join("lib");
6697

98+
// Create a symlink for the generated include directory
99+
refresh_include_symlink(&dst.join("include"));
100+
67101
// Configure Linker to find Slang static library
68102
println!("cargo:rustc-link-search=native={}", lib_dir.display());
69103
println!("cargo:rustc-link-lib=static=svlang");

crates/bender-slang/cpp/slang_bridge.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,9 @@
77
#include "rust/cxx.h"
88
#include "slang/diagnostics/DiagnosticEngine.h"
99
#include "slang/diagnostics/TextDiagnosticClient.h"
10-
#include "slang/driver/Driver.h"
10+
#include "slang/parsing/Preprocessor.h"
1111
#include "slang/syntax/SyntaxTree.h"
12+
#include "slang/text/SourceManager.h"
1213

1314
#include <cstddef>
1415
#include <cstdint>

crates/bender-slang/tests/basic.rs

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
use std::path::PathBuf;
2+
3+
fn fixture_path(rel: &str) -> String {
4+
PathBuf::from(env!("CARGO_MANIFEST_DIR"))
5+
.join("../..")
6+
.join("tests/pickle")
7+
.join(rel)
8+
.canonicalize()
9+
.expect("valid fixture path")
10+
.to_string_lossy()
11+
.into_owned()
12+
}
13+
14+
#[test]
15+
fn parse_valid_file_succeeds() {
16+
let mut session = bender_slang::SlangSession::new();
17+
let files = vec![fixture_path("src/top.sv")];
18+
let includes = vec![fixture_path("include")];
19+
let defines = vec![];
20+
assert!(session.parse_group(&files, &includes, &defines).is_ok());
21+
assert_eq!(session.tree_count(), 1);
22+
}
23+
24+
#[test]
25+
fn parse_invalid_file_returns_parse_error() {
26+
let mut session = bender_slang::SlangSession::new();
27+
let files = vec![fixture_path("src/broken.sv")];
28+
let includes = vec![];
29+
let defines = vec![];
30+
let result = session.parse_group(&files, &includes, &defines);
31+
32+
match result {
33+
Err(bender_slang::SlangError::ParseGroup { .. }) => {}
34+
Err(other) => panic!("expected SlangError::ParseGroup, got {other}"),
35+
Ok(_) => panic!("expected parse to fail"),
36+
}
37+
}
38+
39+
#[test]
40+
fn rewriter_build_from_trees_is_repeatable() {
41+
let mut session = bender_slang::SlangSession::new();
42+
let files = vec![fixture_path("src/top.sv")];
43+
let includes = vec![fixture_path("include")];
44+
let defines = vec![];
45+
session
46+
.parse_group(&files, &includes, &defines)
47+
.expect("parse should succeed");
48+
49+
let trees = session.all_trees().expect("tree collection should succeed");
50+
let mut rewriter_once = bender_slang::SyntaxTreeRewriter::new();
51+
rewriter_once.set_prefix("p_");
52+
rewriter_once.set_suffix("_s");
53+
let first_pass_trees: Vec<_> = trees
54+
.iter()
55+
.map(|t| rewriter_once.rewrite_declarations(t))
56+
.collect();
57+
let renamed_once = rewriter_once.rewrite_references(
58+
first_pass_trees
59+
.first()
60+
.expect("one first-pass tree expected"),
61+
);
62+
assert!(
63+
renamed_once
64+
.display(bender_slang::SlangPrintOpts {
65+
expand_macros: false,
66+
include_directives: true,
67+
include_comments: true,
68+
squash_newlines: false,
69+
})
70+
.contains("module p_top_s (")
71+
);
72+
73+
// Rebuilding with the same trees should remain stable.
74+
let mut rewriter_twice = bender_slang::SyntaxTreeRewriter::new();
75+
rewriter_twice.set_prefix("p_");
76+
rewriter_twice.set_suffix("_s");
77+
let first_pass_trees: Vec<_> = trees
78+
.iter()
79+
.map(|t| rewriter_twice.rewrite_declarations(t))
80+
.collect();
81+
let renamed_twice = rewriter_twice.rewrite_references(
82+
first_pass_trees
83+
.first()
84+
.expect("one first-pass tree expected"),
85+
);
86+
assert!(
87+
renamed_twice
88+
.display(bender_slang::SlangPrintOpts {
89+
expand_macros: false,
90+
include_directives: true,
91+
include_comments: true,
92+
squash_newlines: false,
93+
})
94+
.contains("module p_top_s (")
95+
);
96+
}

tests/cli_regression.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,5 +161,4 @@ regression_tests! {
161161
packages: &["packages"],
162162
packages_graph: &["packages", "--graph"],
163163
packages_flat: &["packages", "--flat"],
164-
165164
}

0 commit comments

Comments
 (0)