1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
// SPDX-License-Identifier: Apache-2.0
//! Central definition of default flag values we expect external tools to use.
//! Keeping them here lets us use these
//! values consistently across the driver code and test that they stay
//! in sync with the underlying tool implementation.
//!
//! NOTE: The single source of truth is still the external tool — these
//! constants must reflect its behaviour. See the unit tests at the
//! bottom of this file which automatically check that the values
//! match the defaults reported by the tools' `--helpfull` so we do
//! not silently diverge.
// -- Codegen flag defaults
/// If true, `codegen_main` inserts runtime assertions that check IR-level
/// invariants (e.g. that a priority selector's one-hot input really is
/// one-hot). Corresponds to `--add_invariant_assertions`. Help output snippet:
///
/// ```text
/// --add_invariant_assertions ... default: true;
/// ```
pub const CODEGEN_ADD_INVARIANT_ASSERTIONS: bool = true;
/// Whether to emit an additional `idle` output signal that indicates no active
/// transaction is flowing through the pipeline. `--add_idle_output`.
pub const CODEGEN_ADD_IDLE_OUTPUT: bool = false;
/// Emit bounds checks for array index operations –
/// `--array_index_bounds_checking`.
pub const CODEGEN_ARRAY_INDEX_BOUNDS_CHECKING: bool = true;
/// When true, Verilog generation uses SystemVerilog features.
/// `--use_system_verilog`.
pub const CODEGEN_USE_SYSTEM_VERILOG: bool = true;
/// Flop (register) all module inputs, `--flop_inputs` (pipeline generator).
pub const CODEGEN_FLOP_INPUTS: bool = true;
/// Flop (register) all module outputs, `--flop_outputs` (pipeline generator).
pub const CODEGEN_FLOP_OUTPUTS: bool = true;
// -- IR converter flag defaults
/// Whether to convert DSLX tests to IR (`--convert_tests`).
/// Help output snippet from `ir_converter_main --helpfull` shows the default.
pub const IR_CONVERTER_CONVERT_TESTS: bool = false;
// -- Tests --------------------------------------------------------------
#[cfg(test)]
mod tests {
use super::*;
use regex::Regex;
use std::process::Command;
/// Panics if preconditions are not met.
fn get_codegen_help() -> String {
let tool_path = std::env::var("XLSYNTH_TOOLS")
.expect("XLSYNTH_TOOLS environment variable must be set for tests");
let codegen_main_path = std::path::Path::new(&tool_path).join("codegen_main");
assert!(
codegen_main_path.exists(),
"codegen_main not found at {:?}",
codegen_main_path
);
let output = Command::new(&codegen_main_path)
.arg("--helpfull")
.output()
.expect("failed to run codegen_main");
// absl::flags exits with code 1 after printing help; accept 0 or 1.
assert!(
matches!(output.status.code(), Some(0) | Some(1)),
"unexpected exit code {:?}",
output.status
);
String::from_utf8_lossy(&output.stdout).into_owned()
}
/// Extracts the default boolean value for `--<flag_name>` from the help
/// text. Panics if the flag or its default is not found.
fn extract_default(help: &str, flag_name: &str) -> bool {
// Regex in DOTALL mode – match everything lazily until we see a
// "default: true;" or "default: false;" capture group.
let pattern = format!(r"--{}[\s\S]*?default: (true|false);", flag_name);
let re = Regex::new(&pattern).expect("invalid regex");
let caps = re.captures(help).unwrap_or_else(|| {
panic!(
"Flag --{} not found in codegen_main --helpfull output",
flag_name
)
});
&caps[1] == "true"
}
#[test]
fn defaults_match_codegen_main() {
let help = get_codegen_help();
let checks: &[(&str, bool)] = &[
("add_invariant_assertions", CODEGEN_ADD_INVARIANT_ASSERTIONS),
("add_idle_output", CODEGEN_ADD_IDLE_OUTPUT),
(
"array_index_bounds_checking",
CODEGEN_ARRAY_INDEX_BOUNDS_CHECKING,
),
("use_system_verilog", CODEGEN_USE_SYSTEM_VERILOG),
("flop_inputs", CODEGEN_FLOP_INPUTS),
("flop_outputs", CODEGEN_FLOP_OUTPUTS),
];
for (flag, expected) in checks {
let actual = extract_default(&help, flag);
assert_eq!(
actual, *expected,
"Default mismatch for flag '--{}': expected {}, got {}",
flag, expected, actual
);
}
}
/// Panics if preconditions are not met.
fn get_ir_converter_help() -> String {
let tool_path = std::env::var("XLSYNTH_TOOLS")
.expect("XLSYNTH_TOOLS environment variable must be set for tests");
let tool = std::path::Path::new(&tool_path).join("ir_converter_main");
assert!(tool.exists(), "ir_converter_main not found at {:?}", tool);
let output = Command::new(&tool)
.arg("--helpfull")
.output()
.expect("failed to run ir_converter_main");
assert!(
matches!(output.status.code(), Some(0) | Some(1)),
"unexpected exit code {:?}",
output.status
);
String::from_utf8_lossy(&output.stdout).into_owned()
}
#[test]
fn defaults_match_ir_converter_main() {
let help = get_ir_converter_help();
let checks: &[(&str, bool)] = &[("convert_tests", IR_CONVERTER_CONVERT_TESTS)];
for (flag, expected) in checks {
let actual = extract_default(&help, flag);
assert_eq!(
actual, *expected,
"Default mismatch for flag '--{}': expected {}, got {}",
flag, expected, actual
);
}
}
}