From bced3f0599f4026b698aeaaf53d5437ba8ef99bc Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 15 Jul 2026 15:15:48 +0000 Subject: [PATCH 1/2] Add an -elab-only flag: stop compilation at the .ba With code generation available from a module's .ba alone (-c) and at link time, a compile no longer needs to produce backend output itself: with -elab-only, compilation stops after elaboration. For the Verilog backend that means genModuleVerilog is not run at all -- exactly as a Bluesim compile already behaves, verified by a test on the -v phase trace -- and each module's .v is generated later, from its .ba, by -c or by the link. The flag is backend-agnostic when compiling source: with -sim (or no backend) stopping at the .ba is already the behavior, so it is accepted as a no-op, letting build systems pass it unconditionally. Skipping codegen means the port properties that getIOProps deduces (const, reg, unused) are absent from the wrapper, as they always are for Bluesim, so a parent that re-exports such a port loses the deduced annotation in its .v header comment. Nothing structural consumes those deduced properties, so the generated modules are otherwise the same as a full compile's. The -u check correspondingly stops expecting .v files from an -elab-only compile, checking the .ba instead. The flag applies only when compiling source (S0100) -- including the no-filenames link path, which bypasses checkLinkFlags -- and cannot be combined with -no-elab, which would suppress the .ba that the deferred code generation needs (S0101). Co-Authored-By: Ravi Nanavati Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01VVN2QMZtLUwkag1vCYLaao --- src/comp/Depend.hs | 6 +- src/comp/Error.hs | 13 ++ src/comp/Flags.hs | 1 + src/comp/FlagsDecode.hs | 29 ++++ src/comp/GenABin.hs | 18 ++- src/comp/bsc.hs | 8 +- testsuite/bsc.options/bsc.help.out.expected | 1 + .../bsc.print-flags-raw.out.expected | 1 + testsuite/bsc.verilog/elab_only/ElabOnly.bsv | 22 +++ testsuite/bsc.verilog/elab_only/Makefile | 5 + testsuite/bsc.verilog/elab_only/elab_only.exp | 147 ++++++++++++++++++ .../bsc.verilog/elab_only/sysETb.out.expected | 1 + 12 files changed, 244 insertions(+), 8 deletions(-) create mode 100644 testsuite/bsc.verilog/elab_only/ElabOnly.bsv create mode 100644 testsuite/bsc.verilog/elab_only/Makefile create mode 100644 testsuite/bsc.verilog/elab_only/elab_only.exp create mode 100644 testsuite/bsc.verilog/elab_only/sysETb.out.expected diff --git a/src/comp/Depend.hs b/src/comp/Depend.hs index 4895aa85c..6c0f5438b 100644 --- a/src/comp/Depend.hs +++ b/src/comp/Depend.hs @@ -236,7 +236,11 @@ getGenFs flags pi = let mod_abin_files = map mkABinFileName (gens pi) in foreign_abin_files ++ mod_abin_files Just Verilog -> - let mod_ver_files = map mkVerFileName (gens pi) + let -- with -elab-only, no .v is written, so a compile is up + -- to date without them (the .ba files are checked instead) + mod_ver_files = if (elabOnly flags) + then [] + else map mkVerFileName (gens pi) foreign_vpi_files = if (useDPI flags) then [] else concatMap mkVPIFileNames (foreigns pi) diff --git a/src/comp/Error.hs b/src/comp/Error.hs index fd86a54cb..73e0cbdd7 100644 --- a/src/comp/Error.hs +++ b/src/comp/Error.hs @@ -1118,6 +1118,8 @@ data ErrMsg = | ETooManyBackends | EDollarNoVerilog | EDollarLink + | EElabOnlyNotSrcCompile + | EElabOnlyNoElab | EWrongBackend String String | ENoOptUndetNoXZ String @@ -4263,6 +4265,17 @@ getErrorText EDollarLink = (System 57, empty, s2par ("The flag -remove-dollar in only supported for compiling source, not linking.")) +getErrorText EElabOnlyNotSrcCompile = + (System 100, empty, + s2par ("The flag -elab-only is only supported when compiling source, " ++ + "not when linking or generating code with -c.")) + +getErrorText EElabOnlyNoElab = + (System 101, empty, + s2par ("The flag -elab-only cannot be combined with -no-elab: " ++ + "suppressing both the .v and the .ba files would leave no " ++ + "generated output.")) + -- Removed System 58 ELicenseUnavailable, BSC is now open source -- Removed System 59 WLicenseExpires, BSC is now open source -- Removed System 60 WWaitForLicense, BSC is now open source diff --git a/src/comp/Flags.hs b/src/comp/Flags.hs index bae934fec..8112e13b1 100644 --- a/src/comp/Flags.hs +++ b/src/comp/Flags.hs @@ -50,6 +50,7 @@ data Flags = Flags { dumps :: [(DumpFlag, Maybe FilePath)], -- dump to file or stdout enablePoisonPills :: Bool, codegenNames :: [String], + elabOnly :: Bool, entry :: Maybe String, expandATSlimit :: Int, expandIf :: Bool, diff --git a/src/comp/FlagsDecode.hs b/src/comp/FlagsDecode.hs index 94812e288..2f1b97d95 100644 --- a/src/comp/FlagsDecode.hs +++ b/src/comp/FlagsDecode.hs @@ -174,6 +174,13 @@ decodeArgs prog args cdir = else -- We allow the file names to be omitted if the -- backend and entry point are both specified case (entry flags) of + -- -elab-only applies to compiling source, + -- not linking (checkLinkFlags rejects it + -- when file names are given) + (Just e) | (elabOnly flags) + -> (warnings, + DError [(cmdPosition, + EElabOnlyNotSrcCompile)]) (Just e) | (backend flags == Just Verilog) -> (warnings, DVerLink flags e [] [] []) (Just e) | (backend flags == Just Bluesim) @@ -261,6 +268,14 @@ checkBSrcFlags flags filename = if (removeVerilogDollar flags && (backend flags /= Just Verilog)) then DError [(cmdPosition, EDollarNoVerilog)] else + -- -elab-only stops compilation at the .ba; for Bluesim (or no + -- backend) stopping there is already the behavior, so the flag + -- is accepted with any backend. Suppressing the .ba as well + -- would leave nothing generated. + if (elabOnly flags && (backend flags /= Nothing) + && not (genABin flags)) + then DError [(cmdPosition, EElabOnlyNoElab)] + else -- If the user hasn't allowed Bluesim/Verilog to diverge, -- then don't-cares can only be 2-state values if (not (optUndet flags) && @@ -296,6 +311,10 @@ checkLinkFlags flags names = if (removeVerilogDollar flags) then DError [(cmdPosition, EDollarLink)] else + -- -elab-only applies to compiling source, not linking + if (elabOnly flags) + then DError [(cmdPosition, EElabOnlyNotSrcCompile)] + else -- Verilog backend if (backend flags == Just Verilog) then -- An entry point must be specified @@ -354,6 +373,10 @@ checkCodeGenFlags flags names = if (genSysC flags) then DError [(cmdPosition, EGenWithSystemC)] else + -- -elab-only suppresses exactly what -c generates + if (elabOnly flags) + then DError [(cmdPosition, EElabOnlyNotSrcCompile)] + else case (backend flags) of Nothing -> DError [(cmdPosition, ENoBackendCodeGen mods)] Just Bluesim -> @@ -601,6 +624,7 @@ defaultFlags bluespecdir = Flags { doICheck = True, dumpAll = Nothing, dumps = [], + elabOnly = False, enablePoisonPills = False, entry = Nothing, expandATSlimit = 20, @@ -1223,6 +1247,10 @@ externalFlags = [ (Toggle (\f x -> f {genABin=x}) (showIfTrue genABin), "generate a .ba file after elaboration and scheduling (on by default with -sim, -verilog and -systemc; -no-elab suppresses)", Visible)), + ("elab-only", + (Toggle (\f x -> f {elabOnly=x}) (showIfTrue elabOnly), + "stop after elaboration: write .ba files but generate no code (-c or linking generates it later)", Visible)), + ("expand-ATS-limit", (Arg "n" (\f s -> case (mread s) of @@ -1909,6 +1937,7 @@ showFlagsRaw flags = ("doICheck", show (doICheck flags)), ("dumpAll", show (dumpAll flags)), ("dumps", show (dumps flags)), + ("elabOnly", show (elabOnly flags)), ("enablePoisonPills", show (enablePoisonPills flags)), ("entry", show (entry flags)), ("expandATSlimit", show (expandATSlimit flags)), diff --git a/src/comp/GenABin.hs b/src/comp/GenABin.hs index 73c15389f..f34c82e1b 100644 --- a/src/comp/GenABin.hs +++ b/src/comp/GenABin.hs @@ -34,7 +34,7 @@ import qualified Data.ByteString as B -- .ba file tag -- change this whenever the .ba format changes -- See also GenBin.header header :: [Byte] -header = B.unpack $ TE.encodeUtf8 $ T.pack "bsc-ba-20260712-2" +header = B.unpack $ TE.encodeUtf8 $ T.pack "bsc-ba-20260712-3" headerBS :: B.ByteString headerBS = B.pack header @@ -568,10 +568,10 @@ instance Bin Flags where a_100 a_101 a_102 a_103 a_104 a_105 a_106 a_107 a_108 a_109 a_110 a_111 a_112 a_113 a_114 a_115 a_116 a_117 a_118 a_119 a_120 a_121 a_122 a_123 a_124 a_125 a_126 a_127 a_128 a_129 - a_130 a_131 a_132 a_133 a_134) = - do wr_chunk0; wr_chunk1; wr_chunk2; wr_chunk3; wr_chunk4; wr_chunk5; wr_chunk6; wr_chunk7; wr_chunk8 + a_130 a_131 a_132 a_133 a_134 a_135) = + do wr_chunk0; wr_chunk1; wr_chunk2; wr_chunk3; wr_chunk4; wr_chunk5; wr_chunk6; wr_chunk7; wr_chunk8; wr_chunk9 where - -- The 135-field serialization is split into NOINLINE chunks so + -- The 136-field serialization is split into NOINLINE chunks so -- that GHC optimizes bounded pieces: compiling it as a single -- monadic chain needs more than 15GB of heap. {-# NOINLINE wr_chunk0 #-} @@ -619,6 +619,9 @@ instance Bin Flags where do toBin a_120; toBin a_121; toBin a_122; toBin a_123; toBin a_124; toBin a_125; toBin a_126; toBin a_127; toBin a_128; toBin a_129; toBin a_130; toBin a_131; toBin a_132; toBin a_133; toBin a_134 + {-# NOINLINE wr_chunk9 #-} + wr_chunk9 = + do toBin a_135 readBytes = do (a_000, a_001, a_002, a_003, a_004, a_005, a_006, a_007, a_008, a_009, a_010, a_011, a_012, a_013, a_014) <- rd_chunk0 @@ -638,6 +641,7 @@ instance Bin Flags where a_113, a_114, a_115, a_116, a_117, a_118, a_119) <- rd_chunk7 (a_120, a_121, a_122, a_123, a_124, a_125, a_126, a_127, a_128, a_129, a_130, a_131, a_132, a_133, a_134) <- rd_chunk8 + (a_135) <- rd_chunk9 return (Flags a_000 a_001 a_002 a_003 a_004 a_005 a_006 a_007 a_008 a_009 a_010 a_011 a_012 a_013 a_014 a_015 a_016 a_017 a_018 a_019 @@ -652,7 +656,7 @@ instance Bin Flags where a_100 a_101 a_102 a_103 a_104 a_105 a_106 a_107 a_108 a_109 a_110 a_111 a_112 a_113 a_114 a_115 a_116 a_117 a_118 a_119 a_120 a_121 a_122 a_123 a_124 a_125 a_126 a_127 a_128 a_129 - a_130 a_131 a_132 a_133 a_134) + a_130 a_131 a_132 a_133 a_134 a_135) where {-# NOINLINE rd_chunk0 #-} rd_chunk0 = @@ -717,6 +721,10 @@ instance Bin Flags where a_130 <- fromBin; a_131 <- fromBin; a_132 <- fromBin; a_133 <- fromBin; a_134 <- fromBin return (a_120, a_121, a_122, a_123, a_124, a_125, a_126, a_127, a_128, a_129, a_130, a_131, a_132, a_133, a_134) + {-# NOINLINE rd_chunk9 #-} + rd_chunk9 = + do a_135 <- fromBin + return (a_135) -- ---------- diff --git a/src/comp/bsc.hs b/src/comp/bsc.hs index 1c2bce208..d17add017 100644 --- a/src/comp/bsc.hs +++ b/src/comp/bsc.hs @@ -953,8 +953,12 @@ genModule -- IO properties which can be included as attributes in the -- Cmoduleverilog (import-BVI) -- XXX it would be nice if the Bluesim backend had the same info + -- With -elab-only, the Verilog backend stops at the .ba, like the + -- Bluesim backend: genModuleVerilog is not run at all, and a later + -- -c or link generates the .v from the .ba. (The wrapper then has + -- no port properties, as with Bluesim.) (t, veriPortProps) - <- if (backend flags == Just Verilog) + <- if (backend flags == Just Verilog && not (elabOnly flags)) then do (t', ips, _v) <- genModuleVerilog errh pps flags dumpnames t prefix modstr @@ -1205,7 +1209,7 @@ genModuleVerilog errh pprops flags dumpnames time0 prefix moduleName -- Return -- * the port properties (to be included in the import-BVI) - -- * the Verilog structure (for accessing in bluetcl) + -- * the Verilog files written return (t, ips, vfilenames) diff --git a/testsuite/bsc.options/bsc.help.out.expected b/testsuite/bsc.options/bsc.help.out.expected index 38736d2e8..d896e045c 100644 --- a/testsuite/bsc.options/bsc.help.out.expected +++ b/testsuite/bsc.options/bsc.help.out.expected @@ -28,6 +28,7 @@ Compiler flags: -demote-errors list treat a list of errors as warnings (``:'' sep list of tags) -e module top-level module for simulation -elab generate a .ba file after elaboration and scheduling (on by default with -sim, -verilog and -systemc; -no-elab suppresses) +-elab-only stop after elaboration: write .ba files but generate no code (-c or linking generates it later) -fdir dir working directory for relative file paths during elaboration -g module generate code for ``module'' (requires -sim or -verilog) -help generate help message diff --git a/testsuite/bsc.options/bsc.print-flags-raw.out.expected b/testsuite/bsc.options/bsc.print-flags-raw.out.expected index 6fd3e86c9..9ccf563a9 100644 --- a/testsuite/bsc.options/bsc.print-flags-raw.out.expected +++ b/testsuite/bsc.options/bsc.print-flags-raw.out.expected @@ -21,6 +21,7 @@ Flags { doICheck = True, dumpAll = Nothing, dumps = [], + elabOnly = False, enablePoisonPills = False, entry = Nothing, expandATSlimit = 20, diff --git a/testsuite/bsc.verilog/elab_only/ElabOnly.bsv b/testsuite/bsc.verilog/elab_only/ElabOnly.bsv new file mode 100644 index 000000000..09914aaf3 --- /dev/null +++ b/testsuite/bsc.verilog/elab_only/ElabOnly.bsv @@ -0,0 +1,22 @@ +// Fixtures for the -elab-only flag (a -verilog compile that writes +// only .ba files, deferring the .v to -c or the linking stage) + +(* synthesize *) +module mkESub(Reg#(Bit#(8))); + Reg#(Bit#(8)) rg <- mkReg(0); + return rg; +endmodule + +(* synthesize *) +module sysETb(Empty); + Reg#(Bit#(8)) sub <- mkESub; + Reg#(Bit#(4)) n <- mkReg(0); + rule bump; + sub <= sub + 2; + n <= n + 1; + if (n == 4) begin + $display("sub = %0d", sub); + $finish(0); + end + endrule +endmodule diff --git a/testsuite/bsc.verilog/elab_only/Makefile b/testsuite/bsc.verilog/elab_only/Makefile new file mode 100644 index 000000000..b953e8132 --- /dev/null +++ b/testsuite/bsc.verilog/elab_only/Makefile @@ -0,0 +1,5 @@ +# for "make clean" to work everywhere + +CONFDIR = $(realpath ../..) + +include $(CONFDIR)/clean.mk diff --git a/testsuite/bsc.verilog/elab_only/elab_only.exp b/testsuite/bsc.verilog/elab_only/elab_only.exp new file mode 100644 index 000000000..a161e5fdb --- /dev/null +++ b/testsuite/bsc.verilog/elab_only/elab_only.exp @@ -0,0 +1,147 @@ +# +# Tests for the -elab-only flag: "bsc -verilog -elab-only" stops after +# elaboration, writing the .ba files but no .v; the Verilog is generated +# later, from the .ba, by -c or by the linking stage. For this design +# that output is byte-identical to what the compile itself would have +# written (the testsuite passes -no-show-timestamps -no-show-version, so +# generated headers are deterministic); in general only deduced +# port-property annotations in a parent's .v header comment can differ. +# + +# Check that none of the listed files exist +proc files_dont_exist { filenames } { + global subdir + + incr_stat "files_dont_exist" + + set foundfile "" + foreach filename $filenames { + set fullname [join [concat $subdir $filename] "/" ] + if {[file exists $fullname]} { + set foundfile $filename + break + } + } + + if {$foundfile == ""} { + pass "found none of the files: $filenames" + } else { + fail "file `$foundfile' should not exist" + } +} + +# run bsc capturing output; expect success +proc elab_run { testname output options } { + set opts "-no-show-timestamps -no-show-version $options" + if [ gen_basic_output $opts $output ] { + pass "$testname" + } else { + fail "$testname should succeed" + } +} + +# ------------------------- +# An -elab-only compile writes the .ba files and no .v + +elab_run "compile with -elab-only" elab1.bsc-out \ + {-verilog -elab-only -u ElabOnly.bsv} +files_exist { mkESub.ba sysETb.ba } +files_dont_exist { mkESub.v sysETb.v } +find_regexp elab1.bsc-out {Elaborated module file created: mkESub\.ba} +find_regexp elab1.bsc-out {Elaborated module file created: sysETb\.ba} +find_regexp_fail elab1.bsc-out {Verilog file created} + +# ------------------------- +# The .ba from an -elab-only compile carries everything code generation +# needs: -c produces each module's .v, byte-identical to what a full +# -verilog compile writes + +elab_run "-c after -elab-only" cgen.bsc-out {-verilog -c mkESub -c sysETb} +files_exist { mkESub.v sysETb.v } +copy mkESub.v mkESub-from-c.v +copy sysETb.v sysETb-from-c.v + +# recompile in full (erase first, so a stale output cannot pass) +erase mkESub.v +erase sysETb.v +compile_verilog_pass ElabOnly.bsv sysETb +compare_file mkESub.v mkESub-from-c.v +compare_file sysETb.v sysETb-from-c.v + +# ------------------------- +# A design compiled with -elab-only links directly: the link generates +# every module's .v from the .ba, and the result simulates + +erase mkESub.v +erase sysETb.v +elab_run "link after -elab-only" vlink.bsc-out \ + {-verilog -e sysETb -o sysETb.vexe} +find_regexp vlink.bsc-out {Verilog file created: mkESub\.v} +find_regexp vlink.bsc-out {Verilog file created: sysETb\.v} +if { $vtest == 1 } { + sim_verilog sysETb + compare_file sysETb.out sysETb.out.expected +} + +# ------------------------- +# -u considers an -elab-only compile up to date without the .v files +# (the .ba files are checked instead) + +erase mkESub.v +erase sysETb.v +elab_run "-u recheck with -elab-only" elabu.bsc-out \ + {-verilog -elab-only -u ElabOnly.bsv} +find_regexp elabu.bsc-out {All packages are up to date} +find_regexp_fail elabu.bsc-out {Elaborated module file created} + +# ... while a full -verilog -u compile still regenerates the missing .v + +elab_run "-u recheck without -elab-only" elabu2.bsc-out \ + {-verilog -u ElabOnly.bsv} +find_regexp elabu2.bsc-out {Verilog file created: mkESub\.v} +find_regexp elabu2.bsc-out {Verilog file created: sysETb\.v} + +# ------------------------- +# Under -v, no backend codegen phase runs with -elab-only: the +# elaboration phases appear (through scheduling and writeABin), but +# none of genModuleVerilog's (foreignMap/astate/.../writeVerilog) + +elab_run "verbose compile with -elab-only" elabv.bsc-out \ + {-verilog -elab-only -v ElabOnly.bsv} +find_regexp elabv.bsc-out {starting schedule} +find_regexp elabv.bsc-out {starting writeABin} +find_regexp_fail elabv.bsc-out {starting foreignMap} +find_regexp_fail elabv.bsc-out {starting astate} +find_regexp_fail elabv.bsc-out {starting IOproperties} +find_regexp_fail elabv.bsc-out {starting verilog} +find_regexp_fail elabv.bsc-out {starting writeVerilog} + +# ------------------------- +# -elab-only is backend-agnostic when compiling source: with -sim (or +# with no backend at all) stopping at the .ba is already the behavior, +# so the flag is accepted as a no-op and build systems can pass it +# unconditionally + +erase mkESub.ba +erase sysETb.ba +elab_run "compile with -sim -elab-only" elabsim.bsc-out \ + {-sim -elab-only ElabOnly.bsv} +files_exist { mkESub.ba sysETb.ba } + +elab_run "compile with -elab-only and no backend" elabnobe.bsc-out \ + {-elab-only ElabOnly.bsv} + +# ------------------------- +# Flag checks: -elab-only applies only when compiling source, and needs +# the .ba output + +# not when linking +compile_no_source_fail_error "elab_only_link" \ + {-no-show-timestamps -no-show-version -verilog -elab-only -e sysETb} S0100 + +# not with -c (it suppresses exactly what -c generates) +compile_no_source_fail_error "elab_only_codegen" \ + {-no-show-timestamps -no-show-version -verilog -elab-only -c mkESub} S0100 + +# not with -no-elab (nothing would be generated at all) +compile_fail_error ElabOnly.bsv S0101 1 {-verilog -elab-only -no-elab} diff --git a/testsuite/bsc.verilog/elab_only/sysETb.out.expected b/testsuite/bsc.verilog/elab_only/sysETb.out.expected new file mode 100644 index 000000000..c828bdca9 --- /dev/null +++ b/testsuite/bsc.verilog/elab_only/sysETb.out.expected @@ -0,0 +1 @@ +sub = 8 From 61c444d823381a313e7177336ebf4b2104cc6b87 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 15 Jul 2026 15:15:48 +0000 Subject: [PATCH 2/2] Document the -elab-only flag Describe deferred code generation in the user guide's codegen-stage section and flag summary, and note in DEVELOP.md that -elab-only skips genModuleVerilog entirely, with the knock-on effect on deduced import-BVI port properties (annotation metadata only; nothing structural consumes them), and that the flag is a no-op for backends that already stop at the .ba. Co-Authored-By: Ravi Nanavati Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01VVN2QMZtLUwkag1vCYLaao --- DEVELOP.md | 17 +++++++++++++++++ doc/user_guide/user_guide.tex | 19 +++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/DEVELOP.md b/DEVELOP.md index 94f05fc3f..bc870c0c8 100644 --- a/DEVELOP.md +++ b/DEVELOP.md @@ -163,6 +163,23 @@ flags are read from the `-c` invocation's command line (elaboration-affecting flags are baked into the `.ba`), and foreign-function `.ba` files are found via the same `-p`/`-bdir` search path as at link time. +The mirror image is `-elab-only`, which makes a `-verilog` compile stop at +the `.ba`, exactly as a Bluesim compile does: `genModuleVerilog` is not run +at all, and every module's `.v` comes from `-c` or the link. The flag is +backend-agnostic when compiling source -- with `-sim` (or no backend) +stopping at the `.ba` is already the behavior, so it is accepted as a +no-op, letting build systems pass it unconditionally. One knock-on +effect: the port properties that `getIOProps` deduces (`const`, `reg`, +`unused`, ...) are a codegen product fed back into the module's import-BVI +wrapper, so under `-elab-only` they are absent -- as they always are for +Bluesim -- and a parent that re-exports such a port loses the deduced +annotation in its own `.v` header comment ("Ports:" blurb) and wrapper. +Nothing structural consumes these deduced properties (the structural ones +-- clock, reset, inout -- are attached by `AState`/`ASyntax` from +`VModInfo`'s clock/reset fields, not from `getIOProps`), so per-module +codegen from a given `.ba` is unchanged; only the annotation metadata in a +parent's output can differ from a full compile's. + ### Bluetcl * [Support for reflection in BSC](https://groups.io/g/b-lang-discuss/message/513) diff --git a/doc/user_guide/user_guide.tex b/doc/user_guide/user_guide.tex index ac9e6c4fa..a17b2e2f3 100644 --- a/doc/user_guide/user_guide.tex +++ b/doc/user_guide/user_guide.tex @@ -827,6 +827,22 @@ \subsubsection{Generating code from elaborated files} example \te{-keep-fires}) take effect from the \te{-c} command line; elaboration choices are already recorded in the \te{.ba} file. +\index{-elab-only@\te{-elab-only} (compiler flag)} +Conversely, a Verilog compile can defer code generation entirely: with +the \te{-elab-only} flag, \te{bsc -verilog -g mkFoo} stops after +elaboration, writing only the \te{.ba} file for each module and no +\te{.v}. The Verilog is then produced from the \te{.ba} files by +\te{-c} commands (for example, run in parallel by an external build +system) or by the linking stage. The generated modules are the same +as a full compile's, except that port-property annotations deduced +during a submodule's code generation (reported in the \te{.v} +file-header comments) may be absent from modules whose submodules were +compiled with \te{-elab-only}. The flag applies when compiling source +with any back end -- a Bluesim compile already stops after elaboration, +so with \te{-sim} it is accepted as a no-op, and build systems can pass +it unconditionally -- and cannot be combined with \te{-no-elab} (which +would suppress the \te{.ba} files that later code generation needs). + For Bluesim, the generated module is a reusable block: its C++ does not depend on where the module is later instantiated. The top module of a Bluesim simulation is the one exception -- it is always generated @@ -1597,6 +1613,7 @@ \subsection{Common compile and linking flags} \index{-e@\te{-e} (compiler flag)} \index{-o@\te{-o} (compiler flag)} \index{-elab@\te{-elab} (compiler flag)} +\index{-elab-only@\te{-elab-only} (compiler flag)} \index{-c@\te{-c} (compiler flag)} \begin{centerboxverbatim} -g module generate code for `module' (requires -sim or -verilog) @@ -1609,6 +1626,8 @@ \subsection{Common compile and linking flags} -o name name of generated executable -elab generate a .ba file after elaboration and scheduling (on by default with -sim and -verilog) +-elab-only stop after elaboration: write .ba files but + generate no code (-c or linking generates it later) \end{centerboxverbatim}