diff --git a/CHANGELOG.md b/CHANGELOG.md index d986c18..c5b1854 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,8 @@ ### Bug Fixes * Fixed `--write path/to/dir/` with directives like `` `default_nettype `` +* Fixed `logic` incorrectly converted to `wire` even when provided to a task or + function output port * Fixed `` `resetall `` not resetting the `` `default_nettype `` ### Other Enhancements diff --git a/src/Convert/Logic.hs b/src/Convert/Logic.hs index caa79d1..5c4ddec 100644 --- a/src/Convert/Logic.hs +++ b/src/Convert/Logic.hs @@ -25,7 +25,7 @@ module Convert.Logic (convert) where -import Control.Monad (when) +import Control.Monad (when, zipWithM) import Control.Monad.Writer.Strict import qualified Data.Map.Strict as Map import qualified Data.Set as Set @@ -37,7 +37,8 @@ import Language.SystemVerilog.AST type Ports = Map.Map Identifier [(Identifier, Direction)] type Location = [Identifier] type Locations = Set.Set Location -type ST = ScoperT Type (Writer Locations) +type DT = (Direction, Type) +type ST = ScoperT DT (Writer Locations) convert :: [AST] -> [AST] convert = @@ -70,16 +71,17 @@ convertDescription ports description = where locations = execWriter $ evalScoperT $ scopePart locScoper description -- write down which vars are procedurally assigned - locScoper = scopeModuleItem traverseDeclM return return traverseStmtM + locScoper = scopeModuleItem + traverseDeclM traverseModuleItemM return traverseStmtM -- rewrite reg continuous assignments and output port connections conScoper = scopeModuleItem - (rewriteDeclM locations) (traverseModuleItemM ports) return return + (rewriteDeclM locations) (rewriteModuleItemM ports) return return -traverseModuleItemM :: Ports -> ModuleItem -> Scoper Type ModuleItem -traverseModuleItemM ports = embedScopes $ traverseModuleItem ports +rewriteModuleItemM :: Ports -> ModuleItem -> Scoper DT ModuleItem +rewriteModuleItemM ports = embedScopes $ rewriteModuleItem ports -traverseModuleItem :: Ports -> Scopes Type -> ModuleItem -> ModuleItem -traverseModuleItem ports scopes = +rewriteModuleItem :: Ports -> Scopes DT -> ModuleItem -> ModuleItem +rewriteModuleItem ports scopes = fixModuleItem where isReg :: LHS -> Bool @@ -92,7 +94,7 @@ traverseModuleItem ports scopes = isReg' :: LHS -> Writer [Bool] () isReg' lhs = case lookupElem scopes lhs of - Just (_, _, t) -> tell [isRegType t] + Just (_, _, (_, t)) -> tell [isRegType t] _ -> tell [False] always_comb = AlwaysC Always . Timing (Event EventStar) @@ -146,14 +148,18 @@ traverseModuleItem ports scopes = maybeModulePorts = Map.lookup moduleName ports fixModuleItem other = other -traverseDeclM :: Decl -> ST Decl -traverseDeclM decl@(Variable _ t x _ _) = - insertElem x t >> return decl -traverseDeclM decl@(Net _ _ _ t x _ _) = - insertElem x t >> return decl -traverseDeclM decl = return decl +traverseModuleItemM :: ModuleItem -> ST ModuleItem +traverseModuleItemM = traverseNodesM traverseExprM return return return return -rewriteDeclM :: Locations -> Decl -> Scoper Type Decl +traverseDeclM :: Decl -> ST Decl +traverseDeclM decl = do + case decl of + Variable d t x _ _ -> insertElem x (d, t) + Net d _ _ t x _ _ -> insertElem x (d, t) + _ -> return () + traverseDeclNodesM return traverseExprM decl + +rewriteDeclM :: Locations -> Decl -> Scoper DT Decl rewriteDeclM locations (Variable d (IntegerVector TLogic sg rs) x a e) = do accesses <- localAccessesM x let location = map accessName accesses @@ -163,11 +169,11 @@ rewriteDeclM locations (Variable d (IntegerVector TLogic sg rs) x a e) = do then do let d' = if d == Inout then Output else d let t' = IntegerVector TReg sg rs - insertElem accesses t' + insertElem accesses (d', t') return $ Variable d' t' x a e else do let t' = Implicit sg rs - insertElem accesses t' + insertElem accesses (d, t') return $ Net d TWire DefaultStrength t' x a e rewriteDeclM locations decl@(Variable d t x a e) = do inProcedure <- withinProcedureM @@ -178,12 +184,12 @@ rewriteDeclM locations decl@(Variable d t x a e) = do (Input, IntegerVector TReg sg rs, False) -> rewriteDeclM locations $ Variable Input t' x a e where t' = IntegerVector TLogic sg rs - _ -> insertElem x t >> return decl + _ -> insertElem x (d, t) >> return decl rewriteDeclM _ (Net d n s (IntegerVector _ sg rs) x a e) = - insertElem x t >> return (Net d n s t x a e) + insertElem x (d, t) >> return (Net d n s t x a e) where t = Implicit sg rs -rewriteDeclM _ decl@(Net _ _ _ t x _ _) = - insertElem x t >> return decl +rewriteDeclM _ decl@(Net d _ _ t x _ _) = + insertElem x (d, t) >> return decl rewriteDeclM _ (Param s (IntegerVector _ sg []) x e) = return $ Param s (Implicit sg [(zero, zero)]) x e where zero = RawNum 0 @@ -195,12 +201,37 @@ traverseStmtM :: Stmt -> ST Stmt traverseStmtM (Asgn op Just{} lhs expr) = -- ignore the timing LHSs traverseStmtM $ Asgn op Nothing lhs expr -traverseStmtM stmt@(Subroutine (Ident f) (Args (_ : Ident x : _) [])) = - when (f == "$readmemh" || f == "$readmemb") (collectLHSM $ LHSIdent x) - >> return stmt +traverseStmtM stmt@(Subroutine (Ident f) (Args (_ : Ident x : _) [])) + | f == "$readmemh" || f == "$readmemb" = + collectLHSM (LHSIdent x) >> return stmt +traverseStmtM (Subroutine fn (Args args [])) = do + fn' <- traverseExprM fn + args' <- traverseCall fn' args + return $ Subroutine fn' $ Args args' [] traverseStmtM stmt = collectStmtLHSsM (collectNestedLHSsM collectLHSM) stmt - >> return stmt + >> traverseStmtExprsM traverseExprM stmt + +traverseExprM :: Expr -> ST Expr +traverseExprM (Call fn (Args args [])) = do + fn' <- traverseExprM fn + args' <- traverseCall fn' args + return $ Call fn' $ Args args' [] +traverseExprM other = + traverseSinglyNestedExprsM traverseExprM other + +traverseCall :: Expr -> [Expr] -> ST [Expr] +traverseCall fn = zipWithM (traverseCallArg fn) [0..] + +-- task and function ports might be outputs, thus requiring a given logic to be +-- a reg rather than a wire +traverseCallArg :: Expr -> Int -> Expr -> ST Expr +traverseCallArg fn idx arg = do + details <- lookupElemM $ Dot fn (show idx) + case (details, exprToLHS arg) of + (Just (_, _, (Output, _)), Just lhs) -> collectLHSM lhs + _ -> return () + return arg -- no rewriting collectLHSM :: LHS -> ST () collectLHSM lhs = do diff --git a/test/core/logic_tf.sv b/test/core/logic_tf.sv index bdd1dcd..98c98f2 100644 --- a/test/core/logic_tf.sv +++ b/test/core/logic_tf.sv @@ -40,4 +40,13 @@ module top; t2(1); $display("%b", t2l); end + + logic l1, l2; + task io_task; + input inp; + output out; + out = ~inp; + endtask + assign l1 = 1; + always_comb io_task(l1, l2); endmodule diff --git a/test/core/logic_tf.v b/test/core/logic_tf.v index 68adce8..c4531b5 100644 --- a/test/core/logic_tf.v +++ b/test/core/logic_tf.v @@ -44,4 +44,10 @@ module top; t2(1); $display("%b", t2l); end + + wire l1; + reg l2; + assign l1 = 1; + always @* + l2 = ~l1; endmodule diff --git a/test/nosim/func_output.sv b/test/nosim/func_output.sv index 4a6ae6f..c3cdf63 100644 --- a/test/nosim/func_output.sv +++ b/test/nosim/func_output.sv @@ -5,7 +5,7 @@ module top; f = x * 3; y = x * 5; endfunction - integer x, y; + logic signed [31:0] x, y; initial x = f(-1, y); initial $display(x, y); endmodule diff --git a/test/nosim/func_output.sv.pat b/test/nosim/func_output.sv.pat new file mode 100644 index 0000000..5e180ae --- /dev/null +++ b/test/nosim/func_output.sv.pat @@ -0,0 +1,2 @@ +affirm reg signed [31:0] x; +affirm reg signed [31:0] y;