Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support splitting up struct method parameters into multiple input ports #729

Open
wants to merge 46 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
49532f4
Initial, hacky work on computing wrapper interface method types using…
krame505 Aug 1, 2024
363cc7b
Attempt at attachting port names with a primative on every input. Do…
krame505 Aug 8, 2024
b24ca9c
Pass the input port names by tagging methods with a new primative
krame505 Aug 10, 2024
92fa2e8
Refactor WrapMethod type class
krame505 Aug 10, 2024
c6b22fa
Input port splitting works end-to-end, modulo sanity checks and savin…
krame505 Aug 13, 2024
57258ec
Handle prefix for input port names via wrap typeclasses
krame505 Aug 13, 2024
8fdb09d
Saving port types using WrapField type class method
krame505 Aug 13, 2024
5945a7c
Bug fixes
krame505 Aug 13, 2024
25695a4
Use WrapField to determine noinline foreign function types
krame505 Aug 14, 2024
6568cc8
Cleanup, add DeepSplitPorts type class
krame505 Aug 14, 2024
1b1f033
Add primMethod wrapper prim calls in vMkRWire1
krame505 Aug 15, 2024
730f044
Update expected test output
krame505 Aug 15, 2024
7975da7
Re-add module arg port type saving, still need to do port name confli…
krame505 Aug 15, 2024
3ba06d4
Fix saving Inout port types
krame505 Aug 15, 2024
96c35e5
Update test expected output
krame505 Aug 15, 2024
d08c97a
Update expected test output
krame505 Aug 15, 2024
b651d36
Fix prefix computation in genwrap 'to' function and port saving state…
krame505 Aug 16, 2024
4020ade
Fix inadvertantly disabled type check for foreign functions
krame505 Aug 16, 2024
2c9e86e
Update test expected results
krame505 Aug 16, 2024
0c15378
Add interface port name sanity checking after elaboration
krame505 Aug 17, 2024
1ecce93
Fix bug introduced in computing split vector interface prefixes
krame505 Aug 17, 2024
936d140
Add sketch of splitting tuples
krame505 Aug 17, 2024
eccaf03
Check for clash with default clock/reset ports
krame505 Aug 17, 2024
4e48c17
Better error message for synthesizing an interface with a non-Bits me…
krame505 Aug 17, 2024
14fb02c
Cleanup trailing whitespace
krame505 Aug 17, 2024
7aea56f
Update expected results, testsuite passing
krame505 Aug 17, 2024
af1e1eb
Reorganize port splitting utilites into a seperate library, add Shall…
krame505 Aug 17, 2024
a52f2e6
More efficient implementation of splitting vectors
krame505 Aug 19, 2024
36a4dc2
Avoid extra _1 suffix for DeepSplitPorts on Int/UInt
krame505 Aug 19, 2024
8999a65
Add test cases for port splitting
krame505 Aug 19, 2024
be3d910
Add test of DeepSplitPorts with an explicit non-recursive instance
krame505 Aug 20, 2024
150d29c
Fix NoSplit instance
krame505 Aug 20, 2024
c8114b1
Add a comment
krame505 Aug 20, 2024
0ea992e
Stuff the field name in the WrapField type class as a type parameter …
krame505 Aug 20, 2024
9d7921f
Fix trailing whitespace
krame505 Aug 20, 2024
f0d8ac7
Addressing Ravi's comments
krame505 Aug 20, 2024
7067fbe
Fix more comments
krame505 Aug 21, 2024
0e23ad0
Fix testsuite failure after error message tweak
krame505 Aug 22, 2024
1329534
Record the full field name path in WrapField context, for better erro…
krame505 Aug 22, 2024
6f8c504
Don't surface implicit conditions from inside ICMethod
krame505 Aug 22, 2024
b1165c9
FIx trailing whitespace
krame505 Aug 23, 2024
0868d79
Slightly less gross list deconstruction in IExpand
krame505 Aug 23, 2024
df0f863
Add more tests
krame505 Aug 23, 2024
d7b1859
Merge remote-tracking branch 'upstream/main' into genwrap
krame505 Aug 23, 2024
82a1c3f
Merge branch 'main' into genwrap
krame505 Oct 18, 2024
5a34e93
Clean up exports
krame505 Jan 21, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Saving port types using WrapField type class method
  • Loading branch information
krame505 committed Aug 13, 2024
commit 8fdb09d2c0dfe16af12cd308b1a46fd59b621b29
115 changes: 81 additions & 34 deletions src/comp/GenWrap.hs
krame505 marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import Prelude hiding ((<>))
#endif

import Data.List(nub, (\\), find)
import Control.Monad(when, foldM, filterM, zipWithM, mapAndUnzipM)
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
Expand All @@ -25,6 +25,7 @@ import IdPrint
import PreIds
import CSyntax
import CSyntaxUtil
import Undefined (UndefKind(..))
import SymTab(SymTab, TypeInfo(..), FieldInfo(..), findType, addTypesUQ,
findField, findFieldInfo, getMethodArgNames)
import MakeSymTab(convCQType)
Expand Down Expand Up @@ -1296,11 +1297,17 @@ mkCtxs ty =
mkNewModDef :: M.Map Id GeneratedIfc -> ModDefInfo -> GWMonad CDefn
mkNewModDef genIfcMap (def@(CDef i (CQType _ t) dcls), cqt, vtis, vps) =
do
--traceM ("mkNewModDef: " ++ ppReadable def)
-- XXX This could have been stored in the moduledef info
-- XXX (note that the first half is the "ts" in "vtis")
let tr = case getArrows t of
(_, TAp _ r) -> r
_ -> internalError "GenWrap.mkNewModDef: tr"
cint <- chkInterface tr
(ifcId, _, fts) <- case cint of
Just res -> return res
Nothing -> internalError "GenWrap.mkNewModDef: cint"

tyId <- flatTypeId vps tr -- id of the Ifc_
let ty = tmod (cTCon tyId) -- type of new module

Expand Down Expand Up @@ -1337,10 +1344,15 @@ mkNewModDef genIfcMap (def@(CDef i (CQType _ t) dcls), cqt, vtis, vps) =
-- statements to record the port-types of module arguments
-- (for the current module)
arg_sptStmts = map (uncurry saveTopModPortTypeStmt) arg_pts

-- interface save-port-type statements
ifc_sptStmts <- mkFieldSavePortTypeStmts Nothing ifcId fts

let sptStmts = arg_sptStmts ++ ifc_sptStmts
-- a do-block around the module body, so that we can include the
-- save-port-type statements
lexp = if not (null arg_sptStmts)
then Cdo False (arg_sptStmts ++ [CSExpr Nothing mexp])
lexp = if not (null sptStmts)
then Cdo False (sptStmts ++ [CSExpr Nothing mexp])
else mexp
-- liftM of the do-block
to = cVApply idLiftM [CVar (to_Id tyId), lexp]
Expand Down Expand Up @@ -1433,7 +1445,7 @@ mkNewModDef _ (def,_,_,_) =
-- This is the part of "genWrapInfo" which makes the DefFun,
-- a continuation function which does the final wrapper computation.

-- type DefFun = VWireInfo -> VSchedInfo -> VPathInfo -> [VPort] -> SymTab -> [VFieldInfo] -> [Id] -> [Id] -> IO CDefn
-- type DefFun = Bool -> VWireInfo -> VSchedInfo -> VPathInfo -> [VPort] -> SymTab -> [VFieldInfo] -> [Id] -> IO CDefn
krame505 marked this conversation as resolved.
Show resolved Hide resolved
-- XXX: alwaysEnabled is dropped and broken (not propagated to {inhigh})
mkDef :: [PProp] -> [PProp] -> CDef -> CQType -> GWMonad DefFun
mkDef iprags pps (CDef i (CQType _ qt) _) cqt = do
Expand All @@ -1447,7 +1459,7 @@ mkDef iprags pps (CDef i (CQType _ qt) _) cqt = do
-- do not use ifc prags here
(st2, ti_) <- runGWMonadGetNoFail (flatTypeId pps tr) st1
let vs = take (length ts) tmpVarIds
(st3, Just (_, _, finfs)) <- runGWMonadGetNoFail (chkInterface tr) st2
(st3, Just (ifcId, _, finfs)) <- runGWMonadGetNoFail (chkInterface tr) st2
let
-- return an expression for creating the arg (from the wrapper's args)
-- and the type of the internal module's arg (for port-type saving)
Expand Down Expand Up @@ -1492,10 +1504,6 @@ mkDef iprags pps (CDef i (CQType _ qt) _) cqt = do
-- make the arg port-types, for saving in the module
arg_pts = mkArgPortTypes wire_info arg_ts
let
-- don't use the "fixed up" veriFields below because we don't need
-- port property information (makes the flow a little simpler, I think)
vfield_map = M.fromList [(vf_name vf, vf) | vf <- fields]

fields' = filter (not . (isRdyToRemoveField (iprags ++ pps))) fields
veriFields = (map (fixupVeriField (iprags ++ pps) ips) fields')
vexp = xWrapperModuleVerilog
Expand All @@ -1509,7 +1517,7 @@ mkDef iprags pps (CDef i (CQType _ qt) _) cqt = do
pathinfo
vlift = (cVApply idLiftModule [vexp])
body <- runGWMonadNoFail
(genFromBody arg_pts vfield_map vlift true_ifc_ids ti_ finfs)
(genFromBody arg_pts vlift true_ifc_ids ti_ ifcId finfs)
st4
let cls = CClause (map CPVar vs) [] body
return $ CValueSign (CDef i cqt [cls]))
Expand All @@ -1534,24 +1542,21 @@ mkArgPortTypes wire_info arg_ts =

-- used in wrapper generate to wrap the module given by mk
-- to the result.
genFromBody :: [(VPort, CType)] -> M.Map Id VFieldInfo ->
CExpr -> [Id] -> Id -> [FInf] -> GWMonad CExpr
genFromBody arg_pts vfield_map mk true_ifc_ids si fts =
genFromBody :: [(VPort, CType)] ->
CExpr -> [Id] -> Id -> Id -> [FInf] -> GWMonad CExpr
genFromBody arg_pts mk true_ifc_ids si ifcId fts =
do
-- traceM( "genFromBody: " ++ ppReadable fts )
let sty = cTCon si
let pos = getIdPosition si
let mkMethod = mkFromBind vfield_map true_ifc_ids (CVar (id_t pos))
(meths, ifc_ptss) <- mapAndUnzipM mkMethod fts
-- TODO: Save "port types" for clocks, resets, inouts here.
let -- interface save-port-type statements
-- XXX need to use the type class here
ifc_sptStmts =
map (uncurry (savePortTypeStmt (CVar id_x))) (concat ifc_ptss)
-- argument save-port-type statements
arg_sptStmts =
let mkMethod = mkFromBind true_ifc_ids (CVar (id_t pos))
meths <- mapM mkMethod fts
-- interface save-port-type statements
ifc_sptStmts <- mkFieldSavePortTypeStmts (Just $ CVar id_x) ifcId fts
-- argument save-port-type statements
let arg_sptStmts =
map (uncurry (savePortTypeStmt (CVar id_x))) arg_pts
sptStmts = arg_sptStmts ++ ifc_sptStmts
sptStmts = arg_sptStmts ++ map CMStmt ifc_sptStmts
let tmpl = Cmodule pos $
[CMStmt $ CSBindT (CPVar (id_t pos)) Nothing [] (CQType [] sty) mk] ++
((saveNameStmt (id_t pos) id_x):sptStmts) ++
Expand All @@ -1560,33 +1565,32 @@ genFromBody arg_pts vfield_map mk true_ifc_ids si fts =
return tmpl


-- Creates a method for the module body
-- also returns the raw port-type information for correlation
-- Creates a method for the module body.
-- XXX some of this can be replaced with a call to "mkFrom_"
-- Currently there is an optimization preventing this - we avoid adding guards for
-- ready signals that are known to be constant True, which isn't known when mkFrom_ is generated.
mkFromBind :: M.Map Id VFieldInfo -> [Id] -> CExpr -> FInf -> GWMonad (CDefl, [(VPort, CType)])
mkFromBind vfield_map true_ifc_ids var ft =
mkFromBind :: [Id] -> CExpr -> FInf -> GWMonad CDefl
mkFromBind true_ifc_ids var ft =
do
ms <- meth noPrefixes ft
return (mkv ms, fth4 ms)
return $ mkv ms
where
mkv (f, e, g, _) = CLValue (setInternal f) [CClause vps [] e'] g
mkv (f, e, g) = CLValue (setInternal f) [CClause vps [] e'] g
where
(vps, e') = unLams e
-- This returns a triple of a field Id (method or subifc),
-- its definition, and its implicit condition (only for methods).
-- Note: The Id is qualified, because it could be something not
-- imported by the user (and this not available unqualified).
meth :: IfcPrefixes -> FInf -> GWMonad (Id, CExpr, [CQual], [(VPort, CType)])
meth :: IfcPrefixes -> FInf -> GWMonad (Id, CExpr, [CQual])
meth prefixes (FInf f as r aIds) =
do
mi <- chkInterface r
case (mi, as) of
(Just (ti, _, fts), []) -> do
newprefixes <- extendPrefixes prefixes [] r f
fieldBlobs <- mapM (meth newprefixes) fts
return (f, cInterface ti (map fst3of4 fieldBlobs), [], concatMap fth4 fieldBlobs)
return (f, cInterface ti fieldBlobs, [])
_ -> do
isVec <- isVectorInterfaces r
case (isVec, as) of
Expand All @@ -1596,9 +1600,9 @@ mkFromBind vfield_map true_ifc_ids var ft =
let recurse num = do newprefixes <- extendPrefixes prefixes [] r f
meth newprefixes (FInf (mkNumId num) [] tVec [])
fieldBlobs <- mapM recurse nums
let (es, gs) = unzip [(e,g) | (_, e, g, _) <- fieldBlobs]
let (es, gs) = unzip [(e,g) | (_, e, g) <- fieldBlobs]
let vec = cToVector isListN es
return (f, vec, concat gs, concatMap fth4 fieldBlobs)
return (f, vec, concat gs)
_ -> do
isPA <- isPrimAction r
isClock <- isClockType r
Expand All @@ -1612,7 +1616,7 @@ mkFromBind vfield_map true_ifc_ids var ft =
let qs = if (wbinf `elem` true_ifc_ids || isClock || isReset || isIot)
then [] else [CQFilter meth_guard]
let e = CApply (CVar id_fromWrapField) [sel binf]
return (f, e, qs, [])
return (f, e, qs)



Expand Down Expand Up @@ -2140,6 +2144,47 @@ saveTopModPortTypeStmt i t =
cVApply idSavePortType
[mkMaybe Nothing, stringLiteralAt noPosition s, typeLiteral t]

-- saveFieldPortTypes v "prefix" ["arg1", "arg2"] "result"
mkFieldSavePortTypeStmts :: Maybe CExpr -> Id -> [FInf] -> GWMonad [CStmt]
mkFieldSavePortTypeStmts v ifcId = concatMapM $ meth noPrefixes
where
meth :: IfcPrefixes -> FInf -> GWMonad [CStmt]
meth prefixes (FInf f as r aIds) =
do
mi <- chkInterface r
case (mi, as) of
(Just (ti, _, fts), []) -> do
newprefixes <- extendPrefixes prefixes [] r f
concatMapM (meth newprefixes) fts
_ -> do
isVec <- isVectorInterfaces r
case (isVec, as) of
(Just (n, tVec, isListN), []) -> do
let nums = [0..(n-1)] :: [Integer]
let recurse num = do newprefixes <- extendPrefixes prefixes [] r f
meth newprefixes (FInf (mkNumId num) [] tVec [])
concatMapM recurse nums
_ -> do
ciPrags <- getInterfaceFieldPrags ifcId f
let methodStr = getIdString f
currentPre = ifcp_renamePrefixes prefixes -- the current rename prefix
localPrefix1 = fromMaybe (getIdString f) (lookupPrefixIfcPragma ciPrags)
localPrefix = joinStrings_ currentPre localPrefix1
mResName = lookupResultIfcPragma ciPrags
resultName = case mResName of
Just str -> joinStrings_ currentPre str
Nothing -> joinStrings_ currentPre methodStr

proxy = mkProxy $ foldr arrow r as
prefix = stringLiteralAt noPosition localPrefix
arg_names = mkList [stringLiteralAt (getPosition i) (getIdString i) | i <- aIds]
result = stringLiteralAt noPosition resultName
return [
CSExpr Nothing $
cVApply id_saveFieldPortTypes
[proxy, mkMaybe v, prefix, arg_names, result]]


saveNameStmt :: Id -> Id -> CMStmt
saveNameStmt svName resultVar = CMStmt (CSletseq [(CLValue resultVar [CClause [] [] nameExpr]) []])
where nameExpr = cVApply idGetModuleName [cVApply idAsIfc [CVar svName]]
Expand Down Expand Up @@ -2179,6 +2224,8 @@ tmod t = TAp (cTCon idModule) t
id_t :: Position -> Id
id_t pos = mkId pos fs_t

mkProxy :: CType -> CExpr
mkProxy ty = CHasType (CAny (getPosition ty) UNotUsed) $ CQType [] ty

-- ====================
-- Ready method utilities
Expand Down
4 changes: 2 additions & 2 deletions src/comp/IExpand.hs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import Data.List
import Data.Maybe
import Data.Foldable(foldrM)
import Numeric(showIntAtBase)
import Data.Char(intToDigit, ord, chr, isDigit)
import Data.Char(intToDigit, ord, chr)
import Control.Monad(when, foldM, zipWithM, mapAndUnzipM)
import Control.Monad.Fix(mfix)
--import Control.Monad.Fix
Expand Down Expand Up @@ -1060,7 +1060,7 @@ iExpandMethodLam :: Id -> Integer -> [Id] -> HPred ->
G ([(Id, IType)], (HDef, HWireSet, VFieldInfo),
(HDef, HWireSet, VFieldInfo))
iExpandMethodLam modId n args implicitCond clkRst (i, bi, ins, eb) li ty p = do
traceM ("iExpandMethodLam " ++ ppString i ++ " " ++ show ins)
-- traceM ("iExpandMethodLam " ++ ppString i ++ " " ++ show ins)
let i' :: Id
i' = mkId (getPosition i) $ mkFString $ head ins
-- substitute argument with a modvar and replace with body
Expand Down
3 changes: 2 additions & 1 deletion src/comp/PreIds.hs
Original file line number Diff line number Diff line change
Expand Up @@ -231,10 +231,11 @@ idPolyWrapField = mk_no fsPolyWrapField
idLiftModule :: Id
idLiftModule = prelude_id_no fsLiftModule

idWrapField, id_fromWrapField, id_toWrapField :: Id
idWrapField, id_fromWrapField, id_toWrapField, id_saveFieldPortTypes :: Id
idWrapField = prelude_id_no fsWrapField
id_fromWrapField = prelude_id_no fsFromWrapField
id_toWrapField = prelude_id_no fsToWrapField
id_saveFieldPortTypes = prelude_id_no fsSaveFieldPortTypes

-- Used by desugaring
id_lam, id_if, id_read, id_write :: Position -> Id
Expand Down
1 change: 1 addition & 0 deletions src/comp/PreStrings.hs
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,7 @@ fsPolyWrapField = mkFString "val"
fsWrapField = mkFString "WrapField"
fsFromWrapField = mkFString "fromWrapField"
fsToWrapField = mkFString "toWrapField"
fsSaveFieldPortTypes = mkFString "saveFieldPortTypes"

-- XXX low ASCII only, please...
sAcute = "__"
Expand Down