@@ -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 (
0 commit comments