22
22
--
23
23
-----------------------------------------------------------------------------
24
24
25
- module GHCi.UI (
25
+ module Clash. GHCi.UI (
26
26
interactiveUI ,
27
27
GhciSettings (.. ),
28
28
defaultGhciSettings ,
29
29
ghciCommands ,
30
- ghciWelcomeMsg
30
+ ghciWelcomeMsg ,
31
+ makeHDL
31
32
) where
32
33
33
34
-- GHCi
34
- import qualified GHCi.UI.Monad as GhciMonad ( args , runStmt , runDecls' )
35
- import GHCi.UI.Monad hiding ( args , runStmt )
36
- import GHCi.UI.Info
37
- import GHCi.UI.Exception
35
+ import qualified Clash. GHCi.UI.Monad as GhciMonad ( args , runStmt , runDecls' )
36
+ import Clash. GHCi.UI.Monad hiding ( args , runStmt )
37
+ import Clash. GHCi.UI.Info
38
+ import Clash. GHCi.UI.Exception
38
39
import GHC.Runtime.Debugger
39
40
import GHC.Runtime.Eval (mkTopLevEnv )
40
41
@@ -96,7 +97,6 @@ import GHC.Utils.Logger
96
97
97
98
-- Other random utilities
98
99
import GHC.Types.Basic hiding ( isTopLevel )
99
- import GHC.Settings.Config
100
100
import GHC.Data.Graph.Directed
101
101
import GHC.Utils.Encoding
102
102
import GHC.Data.FastString
@@ -170,9 +170,27 @@ import GHC.IO.Exception ( IOErrorType(InvalidArgument) )
170
170
import GHC.IO.Handle ( hFlushAll )
171
171
import GHC.TopHandler ( topHandler )
172
172
173
- import GHCi.Leak
173
+ import Clash. GHCi.Leak
174
174
import qualified GHC.Unit.Module.Graph as GHC
175
175
176
+ -- clash additions
177
+ import Clash.Backend (Backend (initBackend , hdlKind , primDirs ))
178
+ import Clash.Backend.SystemVerilog (SystemVerilogState )
179
+ import Clash.Backend.VHDL (VHDLState )
180
+ import Clash.Backend.Verilog (VerilogState )
181
+ import qualified Clash.Driver
182
+ import Clash.Driver.Bool (fromGhcOverridingBool )
183
+ import Clash.Driver.Types (ClashOpts (.. ), ClashEnv (.. ), ClashDesign (.. ))
184
+ import Clash.GHC.Evaluator
185
+ import Clash.GHC.GenerateBindings
186
+ import Clash.GHC.NetlistTypes
187
+ import Clash.GHC.PartialEval
188
+ import Clash.GHCi.Common
189
+ import Clash.Util (clashLibVersion , reportTimeDiff )
190
+ import Data.Proxy
191
+ import qualified Data.Time.Clock as Clock
192
+ import qualified Paths_clash_ghc
193
+
176
194
-----------------------------------------------------------------------------
177
195
178
196
data GhciSettings = GhciSettings {
@@ -183,22 +201,23 @@ data GhciSettings = GhciSettings {
183
201
defPromptCont :: PromptFunction
184
202
}
185
203
186
- defaultGhciSettings :: GhciSettings
187
- defaultGhciSettings =
204
+ defaultGhciSettings :: IORef ClashOpts -> GhciSettings
205
+ defaultGhciSettings opts =
188
206
GhciSettings {
189
- availableCommands = ghciCommands,
207
+ availableCommands = ghciCommands opts ,
190
208
shortHelpText = defShortHelpText,
191
209
defPrompt = default_prompt,
192
210
defPromptCont = default_prompt_cont,
193
211
fullHelpText = defFullHelpText
194
212
}
195
213
196
214
ghciWelcomeMsg :: String
197
- ghciWelcomeMsg = " GHCi, version " ++ cProjectVersion ++
198
- " : https://www.haskell.org/ghc/ :? for help"
215
+ ghciWelcomeMsg = " Clashi, version " ++ Data.Version. showVersion Paths_clash_ghc. version ++
216
+ " (using clash-lib, version " ++ Data.Version. showVersion clashLibVersion ++
217
+ " ):\n https://clash-lang.org/ :? for help"
199
218
200
- ghciCommands :: [Command ]
201
- ghciCommands = map mkCmd [
219
+ ghciCommands :: IORef ClashOpts -> [Command ]
220
+ ghciCommands opts = map mkCmd [
202
221
-- Hugs users are accustomed to :e, so make sure it doesn't overlap
203
222
(" ?" , keepGoing help, noCompletion),
204
223
(" add" , keepGoingPaths addModule, completeFilename),
@@ -252,6 +271,9 @@ ghciCommands = map mkCmd [
252
271
(" undef" , keepGoing undefineMacro, completeMacro),
253
272
(" unset" , keepGoing unsetOptions, completeSetOptions),
254
273
(" where" , keepGoing whereCmd, noCompletion),
274
+ (" vhdl" , keepGoingPaths (makeVHDL opts), completeHomeModuleOrFile),
275
+ (" verilog" , keepGoingPaths (makeVerilog opts), completeHomeModuleOrFile),
276
+ (" systemverilog" ,keepGoingPaths (makeSystemVerilog opts), completeHomeModuleOrFile),
255
277
(" instances" , keepGoing' instancesCmd, completeExpression)
256
278
] ++ map mkCmdHidden [ -- hidden commands
257
279
(" all-types" , keepGoing' allTypesCmd),
@@ -384,6 +406,12 @@ defFullHelpText =
384
406
" :undef <cmd> undefine user-defined command :<cmd>\n " ++
385
407
" ::<cmd> run the builtin command\n " ++
386
408
" :!<command> run the shell command <command>\n " ++
409
+ " :vhdl synthesize currently loaded module to vhdl\n " ++
410
+ " :vhdl [<module>] synthesize specified modules/files to vhdl\n " ++
411
+ " :verilog synthesize currently loaded module to verilog\n " ++
412
+ " :verilog [<module>] synthesize specified modules/files to verilog\n " ++
413
+ " :systemverilog synthesize currently loaded module to systemverilog\n " ++
414
+ " :systemverilog [<module>] synthesize specified modules/files to systemverilog\n " ++
387
415
" \n " ++
388
416
" -- Commands for debugging:\n " ++
389
417
" \n " ++
@@ -483,8 +511,8 @@ default_progname = "<interactive>"
483
511
default_stop = " "
484
512
485
513
default_prompt , default_prompt_cont :: PromptFunction
486
- default_prompt = generatePromptFunctionFromString " ghci > "
487
- default_prompt_cont = generatePromptFunctionFromString " ghci | "
514
+ default_prompt = generatePromptFunctionFromString " clashi > "
515
+ default_prompt_cont = generatePromptFunctionFromString " clashi | "
488
516
489
517
default_args :: [String ]
490
518
default_args = []
@@ -649,31 +677,32 @@ ghciLogAction lastErrLocations old_log_action
649
677
getAppDataFile :: XdgDirectory -> FilePath -> IO (Maybe FilePath )
650
678
getAppDataFile xdgDir file = do
651
679
xdgAppDir <-
652
- tryIO (getXdgDirectory xdgDir " ghc " ) >>= \ case
680
+ tryIO (getXdgDirectory xdgDir " clash " ) >>= \ case
653
681
Left _ -> pure Nothing
654
682
Right dir -> flip catchIO (const $ pure Nothing ) $ do
655
683
createDirectoryIfMissing False dir
656
684
pure $ Just dir
657
685
appDir <-
658
- tryIO (getAppUserDataDirectory " ghc " ) >>= \ case
686
+ tryIO (getAppUserDataDirectory " clash " ) >>= \ case
659
687
Right dir ->
660
688
doesDirectoryExist dir >>= \ case
661
689
True -> pure $ Just dir
662
690
False -> pure xdgAppDir
663
691
Left _ -> pure xdgAppDir
664
692
pure $ appDir >>= \ dir -> Just $ dir </> file
665
693
694
+
666
695
runGHCi :: [(FilePath , Maybe UnitId , Maybe Phase )] -> Maybe [String ] -> GHCi ()
667
696
runGHCi paths maybe_exprs = do
668
697
dflags <- getDynFlags
669
698
let
670
699
ignore_dot_ghci = gopt Opt_IgnoreDotGhci dflags
671
700
672
- appDataCfg = liftIO $ getAppDataFile XdgConfig " ghci .conf"
701
+ appDataCfg = liftIO $ getAppDataFile XdgConfig " clashi .conf"
673
702
674
703
homeCfg = do
675
704
liftIO $ tryIO (getEnv " HOME" ) >>= \ case
676
- Right home -> pure $ Just $ home </> " .ghci "
705
+ Right home -> pure $ Just $ home </> " .clashi "
677
706
_ -> pure Nothing
678
707
679
708
canonicalizePath' :: FilePath -> IO (Maybe FilePath )
@@ -698,7 +727,7 @@ runGHCi paths maybe_exprs = do
698
727
-- Also, let the user silence the message with -v0
699
728
-- (the default verbosity in GHCi is 1).
700
729
when (isNothing maybe_exprs && verbosity dflags > 0 ) $
701
- liftIO $ putStrLn (" Loaded GHCi configuration from " ++ file)
730
+ liftIO $ putStrLn (" Loaded Clashi configuration from " ++ file)
702
731
703
732
--
704
733
@@ -713,7 +742,7 @@ runGHCi paths maybe_exprs = do
713
742
liftIO . fmap (nub . catMaybes) $ mapM canonicalizePath' checkedPaths
714
743
715
744
localCfg <- do
716
- let path = " .ghci "
745
+ let path = " .clashi "
717
746
ok <- liftIO $ checkFileAndDirPerms path
718
747
if ok then liftIO $ canonicalizePath' path else pure Nothing
719
748
@@ -766,10 +795,21 @@ runGHCi paths maybe_exprs = do
766
795
case maybe_exprs of
767
796
Nothing ->
768
797
do
798
+ -- Set different defaulting rules (See #280)
799
+ runGHCiExpressions
800
+ [" default ((), [], Prelude.Integer, Prelude.Int, Prelude.Double, Prelude.String)" ]
801
+
769
802
-- enter the interactive loop
770
803
runGHCiInput $ runCommands $ nextInputLine show_prompt is_tty
771
804
Just exprs -> do
772
805
-- just evaluate the expression we were given
806
+ runGHCiExpressions exprs
807
+
808
+ -- and finally, exit
809
+ liftIO $ when (verbosity dflags > 0 ) $ putStrLn " Leaving Clashi."
810
+
811
+ runGHCiExpressions :: [String ] -> GHCi ()
812
+ runGHCiExpressions exprs = do
773
813
enqueueCommands exprs
774
814
let hdle e = do st <- getGHCiState
775
815
-- flush the interpreter's stdout/stderr on exit (#3890)
@@ -787,9 +827,6 @@ runGHCi paths maybe_exprs = do
787
827
(return Nothing )
788
828
return ()
789
829
790
- -- and finally, exit
791
- liftIO $ when (verbosity dflags > 0 ) $ putStrLn " Leaving GHCi."
792
-
793
830
runGHCiInput :: InputT GHCi a -> GHCi a
794
831
runGHCiInput f = do
795
832
dflags <- getDynFlags
@@ -798,8 +835,8 @@ runGHCiInput f = do
798
835
currentDirectory <- liftIO getCurrentDirectory
799
836
800
837
histFile <- case (ghciHistory, localGhciHistory) of
801
- (True , True ) -> pure $ Just $ currentDirectory </> " .ghci_history "
802
- (True , _) -> liftIO $ getAppDataFile XdgData " ghci_history "
838
+ (True , True ) -> pure $ Just $ currentDirectory </> " .clashi_history "
839
+ (True , _) -> liftIO $ getAppDataFile XdgData " clashi_history "
803
840
_ -> pure Nothing
804
841
805
842
runInputT
@@ -2346,6 +2383,115 @@ runExceptGhciMonad act = handleSourceError printGhciException $
2346
2383
exceptT :: Applicative m => Either e a -> ExceptT e m a
2347
2384
exceptT = ExceptT . pure
2348
2385
2386
+ makeHDL'
2387
+ :: forall backend
2388
+ . Backend backend
2389
+ => Proxy backend
2390
+ -> IORef ClashOpts
2391
+ -> [FilePath ]
2392
+ -> InputT GHCi ()
2393
+ makeHDL' backend opts lst = go =<< case lst of
2394
+ srcs@ (_: _) -> return srcs
2395
+ [] -> do
2396
+ modGraph <- GHC. getModuleGraph
2397
+ let sortedGraph =
2398
+ -- TODO: this might break backpack
2399
+ filterToposortToModules $
2400
+ GHC. topSortModuleGraph False modGraph Nothing
2401
+ return $ case (reverse sortedGraph) of
2402
+ ((AcyclicSCC top) : _) -> maybeToList $ (GHC. ml_hs_file . GHC. ms_location) top
2403
+ _ -> []
2404
+ where
2405
+ go srcs = do
2406
+ dflags <- GHC. getSessionDynFlags
2407
+ goX dflags srcs `MC.finally` recover dflags
2408
+
2409
+ goX dflags srcs = do
2410
+ -- Issue #439 step 1
2411
+ (dflagsX,_,_) <- parseDynamicFlagsCmdLine dflags
2412
+ [ noLoc " -fobject-code" -- For #439
2413
+ , noLoc " -fforce-recomp" -- Actually compile to object-code
2414
+ , noLoc " -keep-tmp-files" -- To prevent linker errors from
2415
+ -- multiple calls to :hdl command
2416
+ ]
2417
+ _ <- GHC. setSessionDynFlags dflagsX
2418
+ reloadModule " "
2419
+ -- Issue #439 step 2
2420
+ -- Unload any object files
2421
+ -- This fixes: https://github.com/clash-lang/clash-compiler/issues/439#issuecomment-522015868
2422
+ env <- GHC. getSession
2423
+ liftIO (Loader. unload (hscInterp env) env [] )
2424
+ -- Finally generate the HDL
2425
+ makeHDL backend (return () ) opts srcs
2426
+
2427
+ recover dflags = do
2428
+ _ <- GHC. setSessionDynFlags dflags
2429
+ reloadModule " "
2430
+
2431
+ makeHDL
2432
+ :: forall backend m
2433
+ . (GHC. GhcMonad m , Backend backend )
2434
+ => Proxy backend
2435
+ -> Ghc ()
2436
+ -> IORef ClashOpts
2437
+ -> [FilePath ]
2438
+ -> m ()
2439
+ makeHDL Proxy startAction optsRef srcs = do
2440
+ dflags <- GHC. getSessionDynFlags
2441
+ liftIO $ do startTime <- Clock. getCurrentTime
2442
+ opts0 <- readIORef optsRef
2443
+ let opts1 = opts0 { opt_color = fromGhcOverridingBool (useColor dflags) }
2444
+ let iw = opt_intWidth opts1
2445
+ hdl = hdlKind backend
2446
+ -- determine whether `-outputdir` was used
2447
+ outputDir = do odir <- objectDir dflags
2448
+ hidir <- hiDir dflags
2449
+ sdir <- stubDir dflags
2450
+ ddir <- dumpDir dflags
2451
+ if all (== odir) [hidir,sdir,ddir]
2452
+ then Just odir
2453
+ else Nothing
2454
+ idirs = importPaths dflags
2455
+ opts2 = opts1 { opt_hdlDir = maybe outputDir Just (opt_hdlDir opts1)
2456
+ , opt_importPaths = idirs}
2457
+ backend = initBackend @ backend opts2
2458
+
2459
+ checkMonoLocalBinds dflags
2460
+ checkImportDirs opts0 idirs
2461
+
2462
+ primDirs_ <- primDirs backend
2463
+
2464
+ forM_ srcs $ \ src -> do
2465
+ -- Generate bindings:
2466
+ let dbs = reverse [p | PackageDB (PkgDbPath p) <- packageDBFlags dflags]
2467
+ (clashEnv, clashDesign) <- generateBindings opts2 startAction primDirs_ idirs dbs hdl src (Just dflags)
2468
+
2469
+ let getMain = getMainTopEntity src clashDesign
2470
+ mainTopEntity <- traverse getMain (GHC. mainFunIs dflags)
2471
+ prepTime <- startTime `deepseq` designBindings clashDesign `deepseq` envTyConMap clashEnv `deepseq` Clock. getCurrentTime
2472
+ let prepStartDiff = reportTimeDiff prepTime startTime
2473
+ putStrLn $ " GHC+Clash: Loading modules cumulatively took " ++ prepStartDiff
2474
+
2475
+ -- Generate HDL:
2476
+ Clash.Driver. generateHDL
2477
+ clashEnv
2478
+ clashDesign
2479
+ (Just backend)
2480
+ (ghcTypeToHWType iw)
2481
+ ghcEvaluator
2482
+ evaluator
2483
+ mainTopEntity
2484
+ startTime
2485
+
2486
+ makeVHDL :: IORef ClashOpts -> [FilePath ] -> InputT GHCi ()
2487
+ makeVHDL = makeHDL' (Proxy @ VHDLState )
2488
+
2489
+ makeVerilog :: IORef ClashOpts -> [FilePath ] -> InputT GHCi ()
2490
+ makeVerilog = makeHDL' (Proxy @ VerilogState )
2491
+
2492
+ makeSystemVerilog :: IORef ClashOpts -> [FilePath ] -> InputT GHCi ()
2493
+ makeSystemVerilog = makeHDL' (Proxy @ SystemVerilogState )
2494
+
2349
2495
-----------------------------------------------------------------------------
2350
2496
-- | @:type@ command. See also Note [TcRnExprMode] in GHC.Tc.Module.
2351
2497
@@ -2885,7 +3031,6 @@ setGHCContextFromGHCiState = do
2885
3031
getImplicitPreludeImports :: GhciMonad m
2886
3032
=> [InteractiveImport ] -> m [InteractiveImport ]
2887
3033
getImplicitPreludeImports iidecls = do
2888
- dflags <- GHC. getInteractiveDynFlags
2889
3034
-- allow :seti to override -XNoImplicitPrelude
2890
3035
st <- getGHCiState
2891
3036
@@ -2894,7 +3039,7 @@ getImplicitPreludeImports iidecls = do
2894
3039
-- of the same module. This means that you can override the prelude import
2895
3040
-- with "import Prelude hiding (map)", for example.
2896
3041
let prel_iidecls =
2897
- if xopt LangExt. ImplicitPrelude dflags && not (any isIIModule iidecls)
3042
+ if not (any isIIModule iidecls)
2898
3043
then [ IIDecl imp
2899
3044
| imp <- prelude_imports st
2900
3045
, not (any (sameImpModule imp) iidecls) ]
@@ -2924,7 +3069,7 @@ iiModuleName (IIModule m) = m
2924
3069
iiModuleName (IIDecl d) = unLoc (ideclName d)
2925
3070
2926
3071
preludeModuleName :: ModuleName
2927
- preludeModuleName = GHC. mkModuleName " Prelude"
3072
+ preludeModuleName = GHC. mkModuleName " Clash. Prelude"
2928
3073
2929
3074
sameImpModule :: ImportDecl GhcPs -> InteractiveImport -> Bool
2930
3075
sameImpModule _ (IIModule _) = False -- we only care about imports here
0 commit comments