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
// SPDX-License-Identifier: Apache-2.0
//! Execution path for the `xlsynth-driver dslx2sv-types` subcommand.
//!
//! This module parses the CLI-selected SV emission policies and routes them to
//! the shared `SvBridgeBuilder` so callers (for example Bazel rules) can
//! choose enum-member spelling and packed-struct bit layout.
use clap::ArgMatches;
use crate::common::get_dslx_paths;
use crate::toolchain_config::ToolchainConfig;
use xlsynth::sv_bridge_builder::{SvEnumCaseNamingPolicy, SvStructFieldOrderingPolicy};
/// Converts DSLX type definitions to SV type declarations and writes the result
/// to stdout.
///
/// This function is intentionally thin: it wires file contents, import search
/// paths, and the caller-selected SV emission policies into the shared bridge
/// implementation. Passing `Unqualified` for a module whose enums reuse case
/// names across types will surface as a generation-time collision error in the
/// builder. Choosing `Reversed` for `struct_field_ordering_policy` changes the
/// packed bit layout of emitted SV structs, not only their textual order.
pub fn dslx2sv_types(
input_file: &std::path::Path,
dslx_stdlib_path: Option<&std::path::Path>,
search_paths: &[&std::path::Path],
enum_case_naming_policy: SvEnumCaseNamingPolicy,
struct_field_ordering_policy: SvStructFieldOrderingPolicy,
) {
log::info!("dslx2sv_types");
let dslx = std::fs::read_to_string(input_file).unwrap();
let dslx_stdlib_path = dslx_stdlib_path;
let additional_search_path_views = search_paths;
let mut import_data =
xlsynth::dslx::ImportData::new(dslx_stdlib_path, additional_search_path_views);
let mut builder = xlsynth::sv_bridge_builder::SvBridgeBuilder::with_policies(
enum_case_naming_policy,
struct_field_ordering_policy,
);
xlsynth::dslx_bridge::convert_leaf_module(&mut import_data, &dslx, input_file, &mut builder)
.unwrap();
let sv = builder.build();
println!("{}", sv);
}
/// Handles the `dslx2sv-types` subcommand from the top-level Clap dispatch.
///
/// The CLI definition in `main.rs` requires and validates
/// `--sv_enum_case_naming_policy` and `--sv_struct_field_ordering` using
/// Clap's `ValueEnum` support on [`SvEnumCaseNamingPolicy`] and
/// [`SvStructFieldOrderingPolicy`], so this function can retrieve typed values
/// directly and then delegate to [`dslx2sv_types`]. Calling this with
/// `ArgMatches` from another subcommand would panic because the code unwraps
/// required `dslx2sv-types` arguments.
pub fn handle_dslx2sv_types(matches: &ArgMatches, config: &Option<ToolchainConfig>) {
log::info!("handle_dslx2sv_types");
let input_file = matches.get_one::<String>("dslx_input_file").unwrap();
let input_path = std::path::Path::new(input_file);
// Clap guarantees presence and allowed values for this flag in the
// `dslx2sv-types` subcommand definition.
let enum_case_naming_policy = *matches
.get_one::<SvEnumCaseNamingPolicy>("sv_enum_case_naming_policy")
.expect("clap should require sv_enum_case_naming_policy");
let struct_field_ordering_policy = *matches
.get_one::<SvStructFieldOrderingPolicy>("sv_struct_field_ordering")
.expect("clap should default sv_struct_field_ordering");
let paths = get_dslx_paths(matches, config);
let dslx_stdlib_path = paths.stdlib_path.as_ref().map(|p| p.as_path());
let search_views = paths.search_path_views();
dslx2sv_types(
input_path,
dslx_stdlib_path,
&search_views,
enum_case_naming_policy,
struct_field_ordering_policy,
);
}