Skip to content

Commit

Permalink
logic conversion handles tf output ports
Browse files Browse the repository at this point in the history
  • Loading branch information
zachjs committed Jun 18, 2024
1 parent 1c90277 commit 73a9cc6
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 26 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
81 changes: 56 additions & 25 deletions src/Convert/Logic.hs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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 =
Expand Down Expand Up @@ -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
Expand All @@ -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)
Expand Down Expand Up @@ -146,14 +148,18 @@ traverseModuleItem ports scopes =
maybeModulePorts = Map.lookup moduleName ports
fixModuleItem other = other

traverseModuleItemM :: ModuleItem -> ST ModuleItem
traverseModuleItemM = traverseNodesM traverseExprM return return return return

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
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 Type 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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand Down
9 changes: 9 additions & 0 deletions test/core/logic_tf.sv
Original file line number Diff line number Diff line change
Expand Up @@ -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
6 changes: 6 additions & 0 deletions test/core/logic_tf.v
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,10 @@ module top;
t2(1);
$display("%b", t2l);
end

wire l1;
reg l2;
assign l1 = 1;
always @*
l2 = ~l1;
endmodule
2 changes: 1 addition & 1 deletion test/nosim/func_output.sv
Original file line number Diff line number Diff line change
Expand Up @@ -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
2 changes: 2 additions & 0 deletions test/nosim/func_output.sv.pat
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
affirm reg signed [31:0] x;
affirm reg signed [31:0] y;

0 comments on commit 73a9cc6

Please sign in to comment.