-
Notifications
You must be signed in to change notification settings - Fork 182
Expand file tree
/
Copy pathGenWrap.hs
More file actions
2297 lines (2051 loc) · 93.7 KB
/
Copy pathGenWrap.hs
File metadata and controls
2297 lines (2051 loc) · 93.7 KB
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
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
{-# LANGUAGE CPP #-}
{-# OPTIONS_GHC -fwarn-name-shadowing #-}
module GenWrap(
genWrap,
WrapInfo(..)
) where
#if defined(__GLASGOW_HASKELL__) && (__GLASGOW_HASKELL__ >= 804)
import Prelude hiding ((<>))
#endif
import Data.Char(isDigit)
import Data.List(nub, (\\), find)
import Control.Monad(when, foldM, filterM, zipWithM)
import Control.Monad.Except(ExceptT, runExceptT, throwError)
import Control.Monad.State(StateT, runStateT, lift, gets, get, put)
import PFPrint
import Position(Position, noPosition, getPositionLine, cmdPosition)
import Error(internalError, EMsg, EMsgs(..), ErrMsg(..), ErrorHandle, bsError)
import ErrorMonad(ErrorMonad, convErrorMonadToIO)
import Flags(Flags)
import FStringCompat
import PreStrings(fsUnderscore, fs_t, fsTo, fsFrom, fsEmpty, fsEnable, fs_rdy, fsDot)
import Id
import IdPrint
import PreIds
import CSyntax
import CSyntaxUtil
import SymTab(SymTab, TypeInfo(..), FieldInfo(..), findType, addTypesUQ,
findField, findFieldInfo, getMethodArgNames)
import MakeSymTab(convCQType)
import Pred hiding (name)
import qualified Pred(name)
import Scheme
import Assump
import CType(cTNum, cTStr, tyConArgs, getArrows, cTVarNum, isIfc, getRes, typeclassId)
import VModInfo(VSchedInfo, VPathInfo(..), VeriPortProp(..), VArgInfo(..),
VFieldInfo(..), VName(..), VWireInfo(..), VPort)
-- GenWrap defines its own versions that expand synonyms and use qualEq
import Type hiding (isPrimAction, isActionValue, getAVType,
isReset, isClock, isInout)
import TypeCheck(cCtxReduceDef)
import Subst(mkSubst, Types(..))
import Classic(isClassic)
import Pragma
import PragmaCheck
import Data.Maybe
import Util
import qualified Data.Map as M
import GenWrapUtils
-- ====================
type GWMonad = StateT GenState (ExceptT EMsgs IO)
data GenState = GenState
{
errHandle :: ErrorHandle,
symtable :: SymTab,
flags :: Flags
}
runGWMonad :: GWMonad a -> GenState -> IO a
runGWMonad f s = do
let errh = errHandle s
result <- runExceptT ((runStateT f) s)
case result of
Right (res, _) -> return res
Left msgs -> bsError errh (errmsgs msgs)
-- don't expect it to fail
runGWMonadNoFail :: GWMonad a -> GenState -> IO a
runGWMonadNoFail f s =
do (_, res) <- runGWMonadGetNoFail f s
return res
-- get the state as well,
-- and we don't expect it to fail
runGWMonadGetNoFail :: GWMonad a -> GenState -> IO (GenState, a)
runGWMonadGetNoFail f s =
do result <- runExceptT ((runStateT f) s)
case result of
Right (res, s2) -> return (s2, res)
Left msgs -> internalError ("runGWMonadGetNoFail: " ++
ppReadable (errmsgs msgs))
-- for converting from ErrorMonad
convEM :: ErrorMonad a -> GWMonad a
convEM m = do
errh <- gets errHandle
lift $ lift $ convErrorMonadToIO errh m
getFlags :: GWMonad Flags
getFlags = gets flags
getSymTab :: GWMonad SymTab
getSymTab = do s <- get
return (symtable s)
newSymTab :: SymTab -> GWMonad ()
newSymTab symtnew = do s <- get
put (s { symtable = symtnew })
bad :: EMsg -> GWMonad a
bad msg = throwError (EMsgs [msg])
bads :: [EMsg] -> GWMonad a
bads msgs = throwError (EMsgs msgs)
-- ====================
-- Field types can these be nested ?
-- Yes fields can be other interfaces
data FInf = FInf
{
name :: Id,
arg_types :: [CType],
ret_type :: CType,
-- a list of any user-provided names (empty if no names)
arg_names :: [Id]
}
deriving (Eq, Show)
instance PPrint FInf where
pPrint d p finf =
text "FInf: " <+>
ppId d (name finf) <+>
pPrint d p (arg_types finf) <+>
pPrint d p (ret_type finf) <+>
pPrint d p (arg_names finf)
instance (HasPosition) FInf where
getPosition finf = getPosition (name finf)
-- ====================
type DefFun = Bool -> VWireInfo -> VSchedInfo -> VPathInfo ->
[VPort] -> SymTab -> [VFieldInfo] -> [Id] ->
IO CDefn
data WrapInfo = WrapInfo
{
mod_nm :: Id, -- module name for synthesis eg mkTest
orig_cqt :: CQType, -- cqtype of original module
wrapper_ifc :: Id, -- munged interface name
wrapped_mod :: Id, -- Id of wrapped module eg. mkTest_
wi_prags :: [PProp],
deffun :: DefFun
}
instance PPrint WrapInfo where
pPrint d p wi@(WrapInfo id1 cqt id2 id3 ps _) =
text "WrapInfo:" <+> ppId d id1 <> text(" :: ") <> pPrint d 0 cqt <>
text(" id2: ") <> ppId d id2 <> text(" id3: ") <>
ppId d id3 $+$
text(" PProps: ")
<> sepList ( map (pPrint d p) ps) (text ",")
-- ====================
-- A shallow processing of the interface of a synthesized module (or of an
-- import-BVI). It lists the original type, it's original field names, and
-- any applicable attributes from the module (such as "always_enabled")
-- and it adds to that some shallow information about the flattened ifc
-- type which will be created later: the name of that type, a list of names
-- of the numeric type arguments that it takes, and a mapping from types in
-- original ifc to their bitified forms in the new ifc (using type names
-- from the argument name list).
-- Until we support synthesis of size-parameterized modules, the argument
-- list and type map will be empty for synthesized modules. Only import-BVI
-- modules will have non-empty lists.
data IfcTRec = IfcTRec
{
rec_id :: Id, -- name of the flattened ifc ("<ifc>_")
rec_rootid :: Id, -- type constructor of the original type
rec_isforeign :: Bool, -- whether it is from an import-BVI
rec_type :: CType, -- the original ifc type
rec_pprops :: [PProp], -- module properties which apply to the ifc
rec_kind :: Kind, -- kind of the flattened ifc
-- (can be derived from the numArgs)
rec_finfs :: [FInf], -- fields of the original ifc
-- with _unqualified_ names
rec_numargs :: [Id], -- names of the numeric type args
-- of the flattened ifc
rec_typemap :: [(CType, CType)] -- mapping from types in the orig ifc
-- to their form in the flattened ifc
}
deriving (Eq, Show)
instance PPrint IfcTRec where
pPrint d p r =
text "IfcTRec:" <+> ppId d (rec_id r) <+> equals <+>
braces (
(if (rec_isforeign r) then text "(Foreign)" else empty) <+>
text "rootid:" <> pPrint d p (rec_rootid r) $+$
text "type:" <> pPrint d p (rec_type r) $+$
text "pprops:" <> pPrint d p (rec_pprops r) $+$
pPrint d p (rec_kind r) $+$
pPrint d p (rec_finfs r) $+$
pPrint d p (rec_numargs r) <+>
pPrint d p (rec_typemap r)
)
-- ====================
-- Information about a flattened, bitified interface
-- The IfcTRec information is further processed (along with the symtab)
-- to create this information.
data GeneratedIfc = GeneratedIfc
{
genifc_id :: Id,
genifc_kind :: Kind,
genifc_cdefn :: CDefn,
genifc_pprops :: [PProp]
}
deriving (Show)
instance PPrint GeneratedIfc where
pPrint d p gifc =
text "GeneratedIfc: " <+> ppId d (genifc_id gifc) <+> equals <+>
braces (
pPrint d p (genifc_cdefn gifc)
$+$ pPrint d p (genifc_pprops gifc)
)
-- ====================
-- Info about modules to be synthesized
-- This data is passed between the stages of "genWrapE"
type ModDefInfo = (CDef, CQType, -- the new "<mod>_" def and it's type
[(Id, CType, ArgInfo)], -- mod arg info with user names
[PProp]) -- pprops on the module
-- ====================
-- Top-level entry: genWrap
-- creates wrappers for separately compiled modules: wraps pack/unpack around method
-- arguments and results; surfaces method ready signals
-- Pragma are module specific
genWrap :: ErrorHandle -> Flags -> [String] -> Bool -> CPackage -> SymTab ->
IO (CPackage, [WrapInfo])
genWrap errh flgs genNames generating cpack symt = do
runGWMonad (genWrapE generating ppmap cpack) origstate
where
origstate = GenState errh symt flgs
pragmas = (extractPragmas cpack)
ppmap = makePPropMap genNames pragmas
--
extractPragmas :: CPackage -> [Pragma]
extractPragmas (CPackage _ _ _ _ _ ds _) = [ p | CPragma p <- ds ]
-- ====================
-- Given a list of names to generate from the command line (with -g flag)
-- and the pragmas from the CPackage, generate a mapping from def names
-- to their associated pprops (removing any duplicate pprops)
makePPropMap :: [String] -> [Pragma] -> M.Map Id [PProp]
makePPropMap genNames cpragmas =
let
-- We avoid adding cmd-line pragmas that duplicate source pragmas,
-- but we don't "nub" the source pragmas and we don't use "union"
-- to construct the map, because we want to preserve the order of
-- "doc" attributes, which don't have to be unique, either.
cmd_line_pragmas = makeCmdLineGenPragmas genNames
all_pragmas = (cmd_line_pragmas \\ cpragmas) ++ cpragmas
pairs = [ (i, pps) | (Pproperties i pps) <- all_pragmas ]
in M.fromListWith (++) pairs
makeCmdLineGenPragmas :: [String] -> [Pragma]
makeCmdLineGenPragmas genNames =
let
-- Turn a string into a qualitifed id with cmdPosition
mId :: String -> Id
mId s =
case span (/= '.') s of
(ms, '.':is) ->
let fms = mkFString ms
fis = mkFString is
in mkQId cmdPosition fms fis
_ ->
let fs = mkFString s
in mkId cmdPosition fs
in [ Pproperties (mId i) [PPverilog] | i <- genNames ]
isGenDef :: M.Map Id [PProp] -> Id -> Bool
isGenDef pmap i =
case (M.lookup i pmap) of
Just pps -> PPverilog `elem` pps
Nothing -> False
-- ====================
-- A new interface is created in the CSyntax, which has the name <Top>_. This interface
-- extends the existing one by adding the ready and enable signals
-- Only modules which have the verilog/synthesis pragma are "wrapped"
genWrapE :: Bool -> M.Map Id [PProp] -> CPackage ->
GWMonad (CPackage, [WrapInfo])
genWrapE generating ppmap cpack@(CPackage packageId exps imps impsigs fixs ds includes) =
do
-- information on all modules which are being generated
-- (this checks the pragmas on all defs which have pragmas, though,
-- and errors if any do not meet sanity checks)
-- moduledefs :: [(CDef, CQType, [(Id, CType, ArgInfo)], [PProp])]
moduledefs <- concatMapM (getDef generating ds) (M.toList ppmap)
--traceM( "genWrapE: moduledefs: " ++ ppReadable moduledefs )
-- build the Interface record
-- this structure should be used throughout
-- ifcTypeRecords :: [IfcTRec]
ifcTypeRecords <- mapM procDef moduledefs
let trs0 = concat ifcTypeRecords
let trs = nub trs0
-- create the type records for Verilog interfaces
(defsWithVector, trs') <- foldM fixVerilogIfc ([],[]) ds
let finalIfcTRecs = nub (trs0 ++ reverse trs')
--traceM( "IfcTRec: " ++ ppReadable finalIfcTRecs )
-- New interface is generated here
-- let newFlatIfcs :: [(Id, Kind, [FInf], CDefn), [PProp]]
newFlatIfcs <- mapM genTDef finalIfcTRecs
let genIfcMap = M.fromList $ map (\g -> (genifc_id g, g)) newFlatIfcs
--traceM ( "genWrapE moduledefs :" ++ ppReadable moduledefs )
--traceM ( "genWrapE ifcTypeRecords : " ++ ppReadable ifcTypeRecords)
----traceM ( "genWrapE old dis_tmp :" ++ ppReadable dis_tmp )
--traceM ( "genWrapE old record :" ++ ppReadable finalIfcTRecs )
--traceM ( "genWrapE new ifc :" ++ ppReadable newFlatIfcs )
-- Update the symbol table for newFlatIfcs
symt <- getSymTab
let symt' = foldr (extSym packageId) symt newFlatIfcs
newSymTab symt'
-- The following make up the new definition list in the CPackage.
let ifcdefns = map genifc_cdefn newFlatIfcs -- new interface definitions
-- create new new module definitions for the CPackage
newModule_s <- mapM (mkNewModDef genIfcMap) moduledefs
to_Defs <- mapM mkTo_ trs
from_Defs <- mapM mkFrom_ trs
let ifcConversionDefs = to_Defs ++ from_Defs
let fixedDefs = map fixDef defsWithVector
instanceDefs <- concatMapM mkInstances trs
-- XXX we don't update the symbol table with the new instances
-- XXX we rely on the symbol table being rebuilt
let finalDefs = reverse fixedDefs ++
ifcdefns ++
newModule_s ++
ifcConversionDefs ++
instanceDefs
gens <- mapM (genWrapInfo newFlatIfcs) moduledefs
--traceM ( "gen wrap: wrapinfo : " ++ ppReadable gens )
----traceM ( "gen Wrap: dis : " ++ ppReadable dis )
----traceM ( "gen wrap: ifcds : " ++ ppReadable ifcds )
--traceM ( "gen wrap: ds_ : " ++ ppReadable newModule_s )
--traceM ( "gen wrap: to_s : " ++ ppReadable ifcConversionDefs )
return (
CPackage packageId exps imps impsigs fixs finalDefs includes,
gens
)
where
-- Adds the new types into the symbol table
extSym :: Id -> GeneratedIfc -> SymTab -> SymTab
extSym mid genifc symt =
-- include both the qualified and unqualified names
addTypesUQ symt [(qdi, tyinf), (di, tyinf)]
where
di = genifc_id genifc
qdi = qualId mid di
k = genifc_kind genifc
-- the type only has parameters if it's a wrapped foreign func
-- (in which case, the params are sizes from added Bits provisos)
-- XXX should we give better names in that case?
vs = []
-- XXX if we need the field names, get them from genifc_cdefn
ti = TIstruct (SInterface noIfcPragmas)
(internalError "extSym: tried to access field names")
tyinf = TypeInfo (Just qdi) k vs ti Nothing
-- removes the [CClause] from the input, and replaces it with singleton list
fixDef :: CDefn -> CDefn
fixDef (CValueSign (CDef defid t e)) | generating &&
isGenDef ppmap defid =
CValueSign (CDef defid t [CClause [] [] (CVar defid)])
fixDef d = d
-- --------------------
-- genWrapE toplevel: procDef
-- This takes the ModDefInfo (computed by getDef) for each module to be
-- synthesized and returns a IfcTRec for each flattened interface that
-- needs to be created. It returns a list because it used to support
-- interface arguments, so it would return the provided interface plus
-- any given interfaces. (Probably only returns one element lists now.)
-- XXX note that it doesn't do a full recursive sweep of the interface
-- Check all definition types and put them in a convenient form
-- XXX the work here is forgotten and repeated many times throughout GenWrap
procDef :: ModDefInfo -> GWMonad [IfcTRec]
procDef (def@(CDef _ t _), _, _, pps) =
do --traceM( "procdef : def= " ++ ppReadable def ) ;
ts <- chkType def t
res <- mapM (makeIfcTRec pps) ts
return res
procDef _ = internalError "genWrapE::procDef not CDef"
-- check that the type being generated is legal (uses the def to get a position)
chkType :: CDef -> CQType -> GWMonad [CType]
chkType def ty =
do
let defId = getDName def
symt <- getSymTab
case convCQType symt ty of
Left msg -> bad msg
Right ((_:_) :=> _) ->
let ctx = if isClassic() then "context" else "proviso"
msg = "It has a " ++ ctx ++ "."
in bad (getPosition def, EBadIfcType (Just $ pfpString defId) msg)
Right ([] :=> t) ->
do
if not (null (tv t))
then let msg = "Its interface is polymorphic."
in bad (getPosition def, EBadIfcType (Just $ pfpString defId) msg)
else
do
--traceM ("chkType: " ++ pfpReadable (t, getArrows t))
case getArrows t of
(args, TAp (TCon (TyCon tm _ _)) tr) | tm == idModule -> do
pint <- getPolyInterface tr
case pint of
-- XXX: should do better with the exact field position
(f:_) -> let msg = "Its interface has a polymorphic field " ++
quote (pfpString f) ++ "."
in bad (getPosition def,
EBadIfcType (Just $ pfpString defId) msg)
[] ->
do
----traceM ("chkType 2: " ++ pfpReadable (chkInterface tr))
cint <- chkInterface tr
case cint of
Just _ ->
do
trs <- getInterfaces args
return (tr : trs)
Nothing -> let msg = "The type " ++
quote (pfpString t) ++
" is not an interface."
in bad (getPosition def,
EBadIfcType (Just $ pfpString defId) msg)
_ -> let msg = "It is not a module."
in bad (getPosition def,
EBadIfcType (Just $ pfpString defId) msg)
-- Return a list of names of any fields which are polymorphic,
-- if the given type is an interface; otherwise return an empty list.
getPolyInterface :: Type -> GWMonad [Id]
getPolyInterface t = do
t' <- expandSynSym t
case (leftCon t') of
Nothing -> return []
Just i -> do
let ts = tyConArgs t'
symt <- getSymTab
case findType symt i of
Just (TypeInfo (Just ti) _ _ (TIstruct ss fs) _) | isIfc ss -> do
res <- filterM (isPolyFieldType ti ts) fs
return res
_ -> return []
-- Build the Interface record
makeIfcTRec :: [PProp] -> Type -> GWMonad IfcTRec
makeIfcTRec pps t =
do res <- chkInterface t
let pps' = filter isRelevantProp pps
case res of
Nothing -> internalError ("makeIfcTRec: not interface - " ++ show t)
Just (_, _, fts) ->
do -- name based on module attributes not ifc attributes
flat_t <- flatTypeId pps' t
raw <- rawTypeId t
let rootId = addInternalProp raw
--
return IfcTRec { rec_id = flat_t,
rec_isforeign = False,
rec_rootid = rootId,
rec_type = t,
rec_pprops = pps',
rec_kind = KStar,
rec_finfs = fts,
rec_numargs = [],
rec_typemap = [] }
-- pulls out all PProps relevant to GenWrap
isRelevantProp :: PProp -> Bool
isRelevantProp (PPalwaysReady {}) = True
isRelevantProp (PPalwaysEnabled {}) = True
isRelevantProp (PPenabledWhenReady {}) = True
isRelevantProp _ = False
-- --------------------
-- genWrapE toplevel: getDef
-- For each definition which has PProps attached to it, this checks
-- the properties, and then for those which are to be generated
-- (that the property PPverilog) it creates a record of information:
-- * The def (possibly updated with a new type if it is to be generated,
-- because polymorphic modules get tied to Module)
-- * The original CQType (before tying down the polymorphic module type)
-- for use on the wrapper around the Verilog
-- * Triples of the names of the module arguments and their types,
-- along with a breakdown of the argument (for Vector arguments)
-- * The list of PProps
getDef :: Bool -> [CDefn] -> (Id, [PProp]) -> GWMonad [ModDefInfo]
getDef generating ds (i, pps) =
do
flgs <- getFlags
symt <- getSymTab
let defs = [ d | d@(CValueSign (CDef i' _ _)) <- ds, unQualId i == unQualId i' ]
case defs of
[d] -> do -- single element list of the module definition
let red = cCtxReduceDef flgs symt d
case red of
Left msgs -> bads msgs
Right (CValueSign (CDef defid cqt@(CQType ctx t) e)) ->
do
t_ext <- expandSynSym t
let ext = (CQType ctx t_ext)
let vts = getDefArgs e t_ext
vtis <- mapM expandArg vts
let pps' = renamePProps vtis pps
-- check pragmas for every def
convEM $ checkModuleArgPragmas (getPosition i) pps pps' vtis
-- only return info for the defs which are generated
if (generating && (PPverilog `elem` pps'))
then do newtyp <- fixupPolyModType ext
return [(CDef defid newtyp e,
cqt, vtis, pps')]
else return []
Right _ -> internalError ("genWrapE::getDef unexpected CtxReduce def" ++ show d )
_ -> bad (getIdPosition i, EUnboundVar (pfpString i))
where
expandArg :: (Id, CType) -> GWMonad (Id, CType, ArgInfo)
expandArg (v_orig, vt_orig) = do
let expandInfo :: Id -> CType -> GWMonad ArgInfo
expandInfo v vt = do
isVector <- isVectorType vt
case isVector of
Just (n,tVec, isListN) -> expandVecInfo v n tVec isListN
_ -> return (Simple v vt)
expandVecInfo :: Id -> Integer -> Type -> Bool -> GWMonad ArgInfo
expandVecInfo v sz tVec isListN = do
-- name the ports p_0, p_1, ...
let mkSuffix n = concatFString [fsUnderscore, mkFString (itos n)]
mkNewName n = mkIdPost v (mkSuffix n)
new_vs = map mkNewName [0..(sz-1)]
-- see if the underlying type is itself a vector
sub_infos <- mapM (`expandInfo` tVec) new_vs
return (Vector isListN v tVec sub_infos)
info <- expandInfo v_orig vt_orig
return (v_orig, vt_orig, info)
-- force IsModule to be Module when we are generating
fixupPolyModType :: CQType -> GWMonad CQType
fixupPolyModType ty =
do
symt <- getSymTab
case convCQType symt ty of
Left msg -> return ty -- let other processing handle the error
-- note that any other provisos will be an error while generating anyway
Right ([pp] :=> t) ->
case (removePredPositions pp) of
(IsIn cls [TVar tv1, TVar tv2]) | (typeclassId (Pred.name cls) == idIsModule)
-> do
let modSubst = mkSubst [(tv1, tModule), (tv2, tId)]
return (CQType [] (apSub modSubst t))
_ -> return ty
_ -> return ty
-- --------------------
-- genWrapE toplevel: genWrapInfo
-- This takes the ModDefInfo (computed by getDef) for each module to be
-- synthesized and generates the WrapInfo structure which is returned
-- from GenWrap (info about the module and a DefFun continuation which is
-- used at the end of synthesis to make the final wrapper).
-- It also takes the list of generated interfaces, in which it will find
-- the info for the interface of the current module.
-- User pragmas are checked that any names match the actual flattened ifc.
-- Pragmas on the ifc type declaration are added to the module's list of
-- pragmas (returned in the WrapInfo).
genWrapInfo :: [GeneratedIfc] -> ModDefInfo -> GWMonad WrapInfo
genWrapInfo genifcs (d@(CDef modName oqt@(CQType _ t) cls), cqt, _, pps) =
do
ifcName_ <- ifcNameFromMod pps t
-- lookup the generate ifc for this module
let mifc = find (qualEq ifcName_ . genifc_id) genifcs
err = internalError ( "genWrapInfo:: cannot find interface " ++
ppReadable ifcName_ ++ ppReadable genifcs )
ifc = maybe err id mifc
let iprops = genifc_pprops ifc
chkUserPragmas pps ifc
-- XXX the new module name should be already created in ModDefInfo,
-- XXX so that it does not have to be created both here and in mkNewModDef
let newModName = modIdRename pps modName
--traceM ("genWrapInfo" ++ ppReadable ifcName_ ++ ppReadable newModName)
--traceM ("genWrapInfo" ++ ppReadable genifcs)
namefun <- mkDef iprops pps d cqt -- pass down the pragma for the wrapper gen state
return WrapInfo { mod_nm = modName,
orig_cqt = oqt,
wrapper_ifc = ifcName_,
wrapped_mod = newModName,
wi_prags = (pps ++ iprops),-- combine pragmas
deffun = namefun }
where
--Get interface name from module XXX make disappear
-- XXX this was already done, but we did not keep the name !
ifcNameFromMod :: [PProp] -> Type -> GWMonad Id
ifcNameFromMod localpps localt = flatTypeIdQual localpps tr
where
tr = case getArrows localt of
(_, TAp _ r) -> r
_ -> internalError "GenWrap.genWrapInfo ifcNameFromMod: tr"
genWrapInfo _ (def,_,_,_) =
internalError( "genWrapInfo: unexpected def: " ++ ppReadable def )
-- --------------------
-- genWrapE toplevel: fixVerilogIfc
-- BSV import-BVI statements have an implied wrapper which converts between
-- the bitified signals and the abstract values. This function looks for
-- import-BVI constructs and inserts the wrapper, also returning an IfcTRec
-- for each new flattended ifc that needs to be declared.
-- finds definitions containing CmoduleVerilog bodies, and alters the
-- name of their interface types to the "derived id":
-- (*A*) Note: this matches syntax generated in CVParserImperative: see
-- the comment labelled (*A*) in CVParserImperative.lhs
-- This looks for CModuleVerilog definition (import BVI), and creates the new definition and
-- IfcTRec for it.
fixVerilogIfc :: ([CDefn], [IfcTRec]) -> CDefn -> GWMonad ([CDefn], [IfcTRec])
fixVerilogIfc (ds,ts) x@(CValueSign (CDef n (CQType prs tid) [CClause ps qs (Cmodule pos body)])) =
do
(newBody, tyrs, prs') <- foldM (fixCModuleVerilog n) ([],[],prs) body
let d'= (CValueSign (CDef n (CQType prs' tid) [CClause ps qs (Cmodule pos (reverse newBody))]))
--
return (d':ds, tyrs++ts)
fixVerilogIfc (ds,ts) d = return ((d:ds),ts)
-- a fix for vectors of interfaces
fixCModuleVerilog :: Id -> ([CMStmt], [IfcTRec], [CPred]) -> CMStmt -> GWMonad ([CMStmt], [IfcTRec], [CPred])
fixCModuleVerilog n (ss,ts,ps)
bdy@(CMStmt (CSBindT p@(CPVar mName) mi pprops cq@(CQType qs ty)
def@(CApply _ [CmoduleVerilog _ _ _ _ aes fs _ _]))) = do
let mStmtSPT = savePortTypeStmt (CVar id_x)
mStmtSPTO = savePortTypeOfStmt (CVar id_x)
let saveArgTypes (Port vp _ _, e) = [mStmtSPTO vp e]
saveArgTypes (InoutArg vn _ _,
CApply (CVar f) [e]) | f == idPrimInoutCast0 =
let vp = (vn,[])
in [mStmtSPTO vp e]
saveArgTypes _ = []
let saveFieldTypes finf (Method { vf_inputs = inps,
vf_outputs = outs }) = do
let rt = ret_type finf
isAV <- isActionValue rt
output_type <- if isAV then getAVType "fixCModVer" rt else return rt
let output_stmt = map ((flip mStmtSPT) rt) outs
-- we let the type-checker error on mismatches
return (output_stmt ++ (zipWith mStmtSPT (concat inps) (arg_types finf)))
saveFieldTypes finf (Inout { vf_inout = vn }) = do
let rt = ret_type finf
vp = (vn,[])
return [mStmtSPT vp rt]
saveFieldTypes _ _ = return []
cint <- chkInterface ty
rawid <- rawTypeId ty
let rootId = addInternalProp rawid
case cint of
Nothing -> bad (getPosition cq, EBadForeignIfcType (pfpString ty))
Just (i, k, fts) ->
do
-- XXX This flattening is redone in genIfcFieldFN
-- XXX We should flatten once -- maybe by storing the flattened FInfs?
let flattenFInfs prefixes (FInf f as r aIds) = do
mifc <- chkInterface r
case (mifc, as) of
(Just (_, _, finfs), []) -> do
newPrefixes <- extendPrefixes prefixes [] r f
meths <- mapM (flattenFInfs newPrefixes) finfs
return (concat meths)
_ -> -- if Vector of ifcs was supported,
-- we'd have to handle it here
return [FInf (binId prefixes f) as r aIds]
flat_fts <- concatMapM (flattenFInfs noPrefixes) fts
let finf_map = M.fromList [(unQualId (name finf), finf) | finf <- flat_fts]
let save_f f =
let fname = vf_name f
in -- imports don't have RDY methods
if (isRdyId fname)
then return []
else case (M.lookup fname finf_map) of
Just finf -> saveFieldTypes finf f
Nothing -> bad (getIdPosition fname,
EForeignModNotField
(pfpString i) (pfpString fname))
save_f_stmtss <- mapM save_f fs
let save_a_stmtss = map saveArgTypes aes
let save_stmts = concat (save_a_stmtss ++ save_f_stmtss)
let pos = getPosition n
ftypes = nub (concatMap (\ (FInf fid as r aIds) -> (r:as)) flat_fts)
(_, numArgs', actualArgs', fieldTypes, ps')
<- foldM procType (0,[],[],[],[]) (reverse ftypes)
let actualArgs = reverse actualArgs'
numArgs = reverse numArgs'
newLeftId = setInternal $
enumId (getIdString i) pos (getPositionLine(pos))
newLeftKind = foldr (\ a lk -> Kfun KNum lk) KStar actualArgs
-- Not actually used, but this is what genIfcFieldFN should produce
-- when it processes the IfcTRec.
newFieldNames = map name flat_fts
newLeftSort = TIstruct (SInterface noIfcPragmas) newFieldNames
newLeftType = TCon (TyCon newLeftId (Just newLeftKind) newLeftSort)
newType = cTApplys newLeftType actualArgs
no_rdys = map (\v -> [vf_name v]) (filter (not . (hasReadyFN fs)) fs)
rdyPPs = case no_rdys of
[] -> []
_ -> [PPalwaysReady no_rdys] -- No ready signals for clocks, resets, etc
s' =(CMStmt
(CSBindT p mi pprops
(CQType qs newType) def))
tr' = IfcTRec { rec_id = newLeftId,
rec_isforeign = True,
rec_rootid = rootId,
rec_type = ty,
rec_pprops = rdyPPs,
rec_kind = newLeftKind,
rec_finfs = fts,
rec_numargs = numArgs,
rec_typemap = fieldTypes }
-- saving port types has to be after the instantiation
-- and saving its name
ss' = save_stmts ++ ((saveNameStmt mName id_x):s':ss)
return (ss', tr':ts, ps' ++ ps)
fixCModuleVerilog n (ss, ts, ps) s = return (s:ss, ts, ps)
procType ::
(Int, [Id], [CType], [(CType, CType)], [CPred]) -> CType ->
GWMonad (
Int, -- next unique num for creating numeric type arg Ids
[Id], -- names of the numeric types created so far (of the form "n_#")
-- as used in the type map below (collected in reverse order)
[CType], -- numeric type variables created so far (of the form "sn_#")
-- as used in the provisos below (collected in reverse order)
[(CType, CType)],
-- map from types in the original ifc to their bitified form
-- (using "n_#" sizes)
[CPred] -- Bits provisos which convert the original types to the
-- numeric types "sn_#"
)
procType (n, ns, as, ts, ctx) ty = do
let hasVars t = not (null (tv t))
newSVar = cTVarNum (enumId "sn" noPosition n)
newId = enumId "n" noPosition n
cBit t = cTApplys tBit [t]
cInout_ t = cTApplys tInout_ [t]
bitsCtx a s = CPred (CTypeclass idBits) [a, s]
isAV <- isActionValue ty
if isAV then do
av_t <- getAVType "procType" ty
return (n+1, newId:ns, newSVar:as,
(ty, (TAp tActionValue_ (TAp tBit (cTVarNum newId)))):ts,
(bitsCtx av_t newSVar):ctx)
else do
isInout <- isInoutType ty
case isInout of
Just t ->
if hasVars t then
return (n+1, newId:ns, newSVar:as,
(ty, cInout_ (cTVarNum newId)):ts,
(bitsCtx t newSVar):ctx)
else return (n, ns, as, ts, ctx)
Nothing ->
if hasVars ty then
return (n+1, newId:ns, newSVar:as,
(ty, cBit (cTVarNum newId)):ts,
(bitsCtx ty newSVar):ctx)
else return (n, ns, as, ts, ctx)
-- --------------------
-- genWrapE toplevel: genTDef
-- Given a IfcTRec structure for the ifc of a synthesized module,
-- produce the
-- Generate a new interface with Id and CDefn
-- Any interface hierarchy is flattened, leaving a new interface
genTDef :: IfcTRec -> GWMonad GeneratedIfc
genTDef trec@(IfcTRec newId rootId _ sty _ k fts args _) =
do
-- generate the new interfaces
(ifc',newprops) <- genIfc trec args k
--traceM( "genTDef: ifc " ++ ppReadable ifc' )
--traceM( "genTDef:: new prop are: " ++ ppReadable newprops )
return GeneratedIfc {
genifc_id = newId,
genifc_kind = k,
genifc_cdefn = ifc',
genifc_pprops = newprops }
-- Generate a new interface definition for the CPackage
-- Basically, this consists of a Cstruct of sub-type Sintrface.
-- The fields are generated in genIfcField
-- accomplished by traversing down the possibly nested interface definitions
-- The props are ones extracted from the ifc, and must be propagated to the module
genIfc :: IfcTRec -> [Id] -> Kind -> GWMonad (CDefn, [PProp] )
genIfc trec args knd =
do let fts = rec_finfs trec
rootId = rec_rootid trec
si = rec_id trec
--traceM("genIfc: " ++ ppReadable trec ) ;
-- lookup interface pragmas from symt and pass them in.
iprags <- getInterfacePrags rootId
let prefix = noPrefixes { ifcp_pragmas = iprags }
fieldprops <- mapM (genIfcField' trec rootId prefix ) fts
let (fields,ppropss) = unzip fieldprops
let newprops = concat ppropss
--
return ( (Cstruct True (SInterface iprags) (IdKind si knd) args ( (concat fields)) []),
newprops )
where
genIfcField' = if rec_isforeign trec
then genIfcFieldFN -- foreign module case
else genIfcField
-- Generate the ifc fields
-- And any new AR AE pragmas from the methods
-- Note: The FInf are assumed to have unqualified field names.
genIfcField :: IfcTRec -> Id -> IfcPrefixes -> FInf -> GWMonad ([CField], [PProp] )
genIfcField trec ifcIdIn prefixes (FInf fieldIdQ argtypes rettype _) =
do
-- get relevant pragmas for this interface and field
--traceM( "prefixes for: " ++ ppReadable fieldId ++ " = " ++ ppReadable prefixes )
-- looking up the pragmas requires the qualified name
ciPrags <- getInterfaceFieldPrags ifcIdIn fieldIdQ
-- but for the rest of the work, we only need the unqualified name
let fieldId = unQualId fieldIdQ
--traceM( "prags for field are: " ++ ppReadable fieldId ++ " = " ++ ppReadable ciPrags)
--
mi <- chkInterface rettype
case mi of
Just (ifcId, k, fts) | null argtypes -> -- recursive function this is an ifc of ifc
do -- create new prefixes before creating new sub-interface fields
newPrefixes <- extendPrefixes prefixes ciPrags rettype fieldId
--
-- if the field is an interface, use its interface Id to
-- recurse and look up field information
fieldsprops <- mapM (genIfcField trec ifcId newPrefixes ) fts
let (fields,props) = unzip fieldsprops
return ((concat fields), (concat props))
_ -> -- leaf function
do
isClock <- isClockType rettype
isReset <- isResetType rettype
isInout <- isInoutType rettype
let isIot = isInout/=Nothing
isPA <- isPrimAction rettype
isVec <- isVectorInterfaces rettype
case (isVec, argtypes) of
(Just (n, tVec, isListN), []) ->
do -- Vectors of interfaces are interfaces
--traceM ("tVec:" ++ (show tVec))
let nums = map mkNumId [0..(n-1)]
newPrefixes <- extendPrefixes prefixes ciPrags rettype fieldId
let recurse num = genIfcField trec ifcIdIn newPrefixes (FInf num [] tVec [])
fieldsprops <- mapM recurse nums
let (fields,props) = unzip fieldsprops
return (concat fields, concat props)
_ -> do -- ELSE NOT a Vec
let fnt = cTStr (fieldPathName prefixes fieldId) (getIdPosition fieldIdQ)
let v = cTVar $ head tmpTyVarIds
let ctx = CPred (CTypeclass idWrapField) [fnt, foldr arrow rettype argtypes, v]
let fi = binId prefixes fieldId
--
let (mprops, ifcPragmas) = gen prefixes ciPrags fieldId fi
gen | isClock = genNewClockIfcPragmas
| isReset = genNewResetIfcPragmas
| isIot = genNewInoutIfcPragmas
| otherwise = genNewMethodIfcPragmas
let ifc_field = CField { cf_name = fi,
cf_pragmas = Just ifcPragmas,
cf_type = CQType [ctx] v,
cf_orig_type = Just (foldr arrow rettype argtypes),
cf_default = []
}
--
-- the ready field
let rdy_field = if (isClock || isReset || isIot) then []
else mkReadyField trec ifcPragmas ifcIdIn fieldId fi
--
--traceM( "ifc_fields is: " ++ ppReadable ifc_field)
return ((ifc_field : rdy_field), mprops )
-- create a RDY field, if requested
mkReadyField :: IfcTRec -> [IfcPragma] -> Id -> Id -> Id -> [CField]
mkReadyField trec ifcprags rootIfcId fieldId pathFieldId = if makingReady then [cfield] else []
where pps = rec_pprops trec
readyId = mkRdyId pathFieldId -- why mkRdyId only to compare it later?
makingReady = not ((isAlwaysRdy pps readyId) || (isAlwaysReadyIfc ifcprags) )
--
renamed = mkRdyId pathFieldId
cfield = CField { cf_name = renamed,
cf_pragmas = Nothing,
cf_type = (CQType [] (TAp tBit (cTNum 1 (getPosition fieldId)))),
cf_orig_type = Nothing,
cf_default = []
}
-- The same (as genIfcField) but for foreign modules.
-- Note: The FInf are assumed to have unqualified field names.
genIfcFieldFN :: IfcTRec -> Id -> IfcPrefixes -> FInf -> GWMonad ( [CField], [PProp])
genIfcFieldFN trec rootId prefixes (FInf fieldIdQ argtypes r _) =
do
let typeMap = rec_typemap trec
-- looking up the pragmas requires the qualified name
ciPrags <- getInterfaceFieldPrags rootId fieldIdQ
-- but for the rest of the work, we only need the unqualified name
let fieldId = unQualId fieldIdQ
mi <- chkInterface r
case mi of
Just (ifcId, k, fts) | null argtypes -> -- recursive function this is an ifc of ifc
do -- create new prefixes before creating new sub-interface fields
newPrefixes <- extendPrefixes prefixes ciPrags r fieldId
--
-- if the field is an interface, use its interface Id to recurse and look up field information
fieldsprops <- mapM (genIfcFieldFN trec ifcId newPrefixes ) fts
let (fields,props) = unzip fieldsprops
return ((concat fields), (concat props))
Just _ -> -- recursive interface def
internalError ( "genIfcFieldFN -- invalid hierarchy of interfaces" )
Nothing -> -- leaf function
do
symt <- getSymTab
let (v, vs) = unconsOrErr "GenWrap.genIfcFieldFN: v:vs" $
map cTVarNum (take (length argtypes + 1) tmpTyVarIds)
isTClock t = t == tClock
isTReset t = t == tReset
isTInout t = (leftCon t == Just idInout)
bitsCtx a s = CPred (CTypeclass idBits) [a, s]
newTypeCtx t lctx lv =
case lookup t typeMap of
Just t' -> (t', lctx)
Nothing ->
let newTCtx
| isTClock t = (t,lctx)
| isTReset t = (t,lctx)
| leftCon t == Just idBit = (t,lctx)
| leftCon t == Just idActionValue_ = (t,lctx)
| leftCon t == Just idActionValue = (t,lctx)
| isTInout t =
let it = headOrErr "inout arg" (tyConArgs t)
in (TAp tInout_ lv, bitsCtx it lv : lctx)
| otherwise =
(TAp tBit lv, bitsCtx t lv : lctx)
in newTCtx
fldfn (t,lv) (largtypes,lctx) =
let (t',ctx') = newTypeCtx t lctx lv