From b6f4f690e7f7076cf76cd8a01b066048cdc5196c Mon Sep 17 00:00:00 2001 From: Zachary Snow Date: Wed, 3 Jun 2020 20:18:14 -0400 Subject: [PATCH] support simple bundle interfaces - fix position modport-to-modport bindings - inout logics converted to regs become outputs --- src/Convert/Interface.hs | 101 +++++++++++++++++++++---------- src/Convert/Logic.hs | 6 +- test/basic/interface_bundle.sv | 43 +++++++++++++ test/basic/interface_bundle.v | 38 ++++++++++++ test/relong/complex_interface.sv | 12 +++- 5 files changed, 165 insertions(+), 35 deletions(-) create mode 100644 test/basic/interface_bundle.sv create mode 100644 test/basic/interface_bundle.v diff --git a/src/Convert/Interface.hs b/src/Convert/Interface.hs index 06539f2..1b44573 100644 --- a/src/Convert/Interface.hs +++ b/src/Convert/Interface.hs @@ -73,6 +73,11 @@ convertDescription interfaces modules (Part attrs extern Module lifetime name po InterfaceT interfaceName (Just modportName) [] -> tell (Map.empty, Map.singleton ident modportDecls) where Just modportDecls = lookupModport interfaceName modportName + Alias Nothing interfaceName [] -> + case impliedModport interfaceName of + Just modportDecls -> + tell (Map.empty, Map.singleton ident modportDecls) + Nothing -> return () _ -> return () collectInterface (Instance part _ ident Nothing _) = if Map.member part interfaces @@ -81,7 +86,7 @@ convertDescription interfaces modules (Part attrs extern Module lifetime name po collectInterface _ = return () mapInterface :: ModuleItem -> ModuleItem - mapInterface (orig @ (MIPackageItem (Decl (Variable Local t ident _ _)))) = + mapInterface (orig @ (MIPackageItem (Decl (Variable _ t ident _ _)))) = -- expand instantiation of a modport case Map.lookup ident modports of Just modportDecls -> Generate $ @@ -89,7 +94,10 @@ convertDescription interfaces modules (Part attrs extern Module lifetime name po modportDecls Nothing -> orig where - InterfaceT interfaceName (Just _) [] = t + interfaceName = case t of + InterfaceT x (Just _) [] -> x + Alias Nothing x [] -> x + _ -> error $ "unexpected modport type " ++ show t interfaceItems = case Map.lookup interfaceName interfaces of Just res -> snd res @@ -128,48 +136,61 @@ convertDescription interfaces modules (Part attrs extern Module lifetime name po expandPortBinding _ (origBinding @ (portName, Just (Dot (Ident instanceName) modportName))) _ = -- expand instance modport bound to a modport if Map.member instanceName instances && modportDecls /= Nothing - then map mapper $ fromJust modportDecls + then expandPortBinding' portName instanceName $ fromJust modportDecls else [origBinding] where interfaceName = instances Map.! instanceName modportDecls = lookupModport interfaceName modportName - mapper (_, x, me) = (portName ++ "_" ++ x, me') - where me' = fmap (traverseNestedExprs prefixExpr) me - prefixExpr :: Expr -> Expr - prefixExpr (Ident x) = Ident (instanceName ++ "_" ++ x) - prefixExpr other = other expandPortBinding moduleName (origBinding @ (portName, Just (Ident ident))) idx = case (instances Map.!? ident, modports Map.!? ident) of (Nothing, Nothing) -> [origBinding] - (Just _, _) -> + (Just interfaceName, _) -> -- given entire interface, but just bound to a modport - expandPortBinding moduleName (portName', Just newExpr) idx + if Map.notMember moduleName modules then + error $ "could not find module " ++ show moduleName + else if modportDecls == Nothing then + [origBinding] + else + expandPortBinding' portName ident $ fromJust modportDecls where - (portName', InterfaceT _ (Just modportName) []) = - case (portName, Map.lookup moduleName modules) of - ("", Just decls) -> - if idx < length decls - then decls !! idx - else error $ "could not infer port " - ++ show origBinding ++ " in module " - ++ show moduleName - (_, Just decls) -> case lookup portName decls of - Nothing -> error $ "could not find port " - ++ show portName ++ " in module " - ++ show moduleName - Just t -> (portName, t) - (_, Nothing) -> error $ "could not find module " + Just decls = Map.lookup moduleName modules + portType = + if null portName + then if idx < length decls + then snd $ decls !! idx + else error $ "could not infer port " + ++ show origBinding ++ " in module " ++ show moduleName - newExpr = Dot (Ident ident) modportName - (_, Just decls) -> + else case lookup portName decls of + Nothing -> error $ "could not find port " + ++ show portName ++ " in module " + ++ show moduleName + Just t -> t + modportDecls = + case portType of + InterfaceT _ (Just modportName) [] -> + lookupModport interfaceName modportName + Alias Nothing _ [] -> + impliedModport interfaceName + _ -> Nothing + (_, Just modportDecls) -> -- modport directly bound to a modport - map mapper decls - where - mapper (_, x, _) = - ( portName ++ "_" ++ x - , Just $ Dot (Ident ident) x ) + expandPortBinding' portName ident $ map redirect modportDecls + where redirect (d, x, _) = (d, x, Just $ Ident x) expandPortBinding _ other _ = [other] + expandPortBinding' :: Identifier -> Identifier -> [ModportDecl] -> [PortBinding] + expandPortBinding' portName instanceName modportDecls = + map mapper modportDecls + where + mapper (_, x, me) = (x', me') + where + x' = if null portName then "" else portName ++ '_' : x + me' = fmap (traverseNestedExprs prefixExpr) me + prefixExpr :: Expr -> Expr + prefixExpr (Ident x) = Ident (instanceName ++ '_' : x) + prefixExpr other = other + lookupModport :: Identifier -> Identifier -> Maybe [ModportDecl] lookupModport interfaceName = if Map.member interfaceName interfaces @@ -184,6 +205,22 @@ convertDescription interfaces modules (Part attrs extern Module lifetime name po collectModport (Modport ident l) = tell $ Map.singleton ident l collectModport _ = return () + impliedModport :: Identifier -> Maybe [ModportDecl] + impliedModport interfaceName = + if Map.member interfaceName interfaces + then Just modport + else Nothing + where + interfaceItems = snd $ interfaces Map.! interfaceName + modport = execWriter $ + mapM (collectNestedModuleItemsM collectModportDecls) $ + interfaceItems + collectModportDecls :: ModuleItem -> Writer [ModportDecl] () + collectModportDecls (MIPackageItem (Decl (Variable d _ x _ _))) = + tell [(d', x, Just $ Ident x)] + where d' = if d == Local then Inout else d + collectModportDecls _ = return () + convertExpr :: Instances -> Modports -> Expr -> Expr convertExpr its mps (orig @ (Dot (Ident x) y)) = if Map.member x mps || Map.member x its @@ -263,7 +300,7 @@ lookupType items (Ident ident) = ts -> head ts where findType :: ModuleItem -> Maybe (Type, [Range]) - findType (MIPackageItem (Decl (Variable _ t x rs Nothing))) = + findType (MIPackageItem (Decl (Variable _ t x rs _))) = if x == ident then Just (t, rs) else Nothing findType _ = Nothing lookupType _ expr = diff --git a/src/Convert/Logic.hs b/src/Convert/Logic.hs index 794fae3..6db8875 100644 --- a/src/Convert/Logic.hs +++ b/src/Convert/Logic.hs @@ -122,11 +122,15 @@ convertDescription ports orig = -- rewrite variable declarations to have the correct type convertModuleItem (MIPackageItem (Decl (Variable dir (IntegerVector _ sg mr) ident a me))) = - MIPackageItem $ Decl $ Variable dir (t mr) ident a me + MIPackageItem $ Decl $ Variable dir' (t mr) ident a me where t = if Set.member ident fixedIdents then IntegerVector TReg sg else Net (NetType TWire) sg + dir' = + if dir == Inout && Set.member ident fixedIdents + then Output + else dir convertModuleItem other = other -- all other logics (i.e. inside of functions) become regs convertDecl :: Decl -> Decl diff --git a/test/basic/interface_bundle.sv b/test/basic/interface_bundle.sv new file mode 100644 index 0000000..e494a25 --- /dev/null +++ b/test/basic/interface_bundle.sv @@ -0,0 +1,43 @@ +interface bundle; + logic [1:0] index; + logic clock; + logic [3:0] inp; + logic out; +endinterface + +module rotator(bundle b); + initial b.index = 0; + always @(posedge b.clock) + b.index <= b.index + 1; +endmodule + +module setter(bundle b); + initial b.inp = '1; + always @(posedge b.clock) + b.inp[b.index] <= b.out; +endmodule + +module reducer(bundle b); + assign b.out = ^b.inp; +endmodule + +module clocker(bundle b); + initial begin + b.clock <= 0; + forever + #5 b.clock <= ~b.clock; + end +endmodule + +module top; + bundle b(); + rotator rot(b); + setter set(b); + reducer red(b); + clocker clk(b); + initial begin + $monitor("%b %b %b %b", b.index, b.clock, b.inp, b.out); + #100; + $finish; + end +endmodule diff --git a/test/basic/interface_bundle.v b/test/basic/interface_bundle.v new file mode 100644 index 0000000..e7ad151 --- /dev/null +++ b/test/basic/interface_bundle.v @@ -0,0 +1,38 @@ +module impl(b_index, b_clock, b_inp, b_out); + output reg [1:0] b_index; + output reg b_clock; + output reg [3:0] b_inp; + output wire b_out; + + initial b_index = 0; + always @(posedge b_clock) + b_index <= b_index + 1; + + initial b_inp = 4'b1111; + always @(posedge b_clock) + b_inp[b_index] <= b_out; + + assign b_out = ^b_inp; + + initial begin + b_clock <= 0; + forever + #5 b_clock <= ~b_clock; + end +endmodule + +module top; + wire [1:0] b_index; + wire b_clock; + wire [3:0] b_inp; + wire b_out; + + impl impl(b_index, b_clock, b_inp, b_out); + + initial begin + $monitor("%b %b %b %b", b_index, b_clock, b_inp, b_out); + #100; + $finish; + end +endmodule + diff --git a/test/relong/complex_interface.sv b/test/relong/complex_interface.sv index 61c01d2..d05fefb 100644 --- a/test/relong/complex_interface.sv +++ b/test/relong/complex_interface.sv @@ -24,7 +24,7 @@ module CacheWithInterface( .response(myResponse) ); - CacheSet set( + CacheSetWrapper set( .data(dataInterface.CacheSet), .clock, .clear @@ -35,6 +35,14 @@ module CacheWithInterface( endmodule +// to test binding a modport to another modport +module CacheSetWrapper ( + CacheSetInterface.CacheSet data, + input logic clock, clear +); + CacheSet set(data, clock, clear); +endmodule + module CacheSet ( CacheSetInterface.CacheSet data, input logic clock, clear @@ -46,4 +54,4 @@ module CacheSet ( else data.response <= ~data.request; -endmodule \ No newline at end of file +endmodule