From 326048aeac6f846d8ad52c2a66f73219426f8bea Mon Sep 17 00:00:00 2001 From: Yann Herklotz Date: Mon, 26 Apr 2021 11:38:55 +0100 Subject: Fix parser for a larger set of inputs - Added support for parameter parsing - Added support for parameter declaration for instantiations - Fix parsing of @(*) - Fix parsing of `timescale - Add parsing for case statements with default --- src/Verismith/Generate.hs | 4 +-- src/Verismith/Reduce.hs | 8 ++--- src/Verismith/Verilog/AST.hs | 7 ++-- src/Verismith/Verilog/CodeGen.hs | 3 +- src/Verismith/Verilog/Distance.hs | 2 +- src/Verismith/Verilog/Internal.hs | 1 + src/Verismith/Verilog/Mutate.hs | 8 ++--- src/Verismith/Verilog/Parser.hs | 66 ++++++++++++++++++++++++++++--------- src/Verismith/Verilog/Preprocess.hs | 2 ++ 9 files changed, 71 insertions(+), 30 deletions(-) diff --git a/src/Verismith/Generate.hs b/src/Verismith/Generate.hs index 51bd066..ecf96e3 100644 --- a/src/Verismith/Generate.hs +++ b/src/Verismith/Generate.hs @@ -542,8 +542,8 @@ instantiate (ModDecl i outP inP _ _) = do $ inpFixed ^.. traverse . portSize ident <- makeIdentifier "modinst" Hog.choice - [ return . ModInst i ident $ ModConn <$> (toE (outs <> clkPort <> ins) <> insLit), - ModInst i ident + [ return . ModInst i [] ident $ ModConn <$> (toE (outs <> clkPort <> ins) <> insLit), + ModInst i [] ident <$> Hog.shuffle ( zipWith ModConnNamed diff --git a/src/Verismith/Reduce.hs b/src/Verismith/Reduce.hs index 267dddb..cc7d60b 100644 --- a/src/Verismith/Reduce.hs +++ b/src/Verismith/Reduce.hs @@ -294,7 +294,7 @@ isModule :: Identifier -> (ModDecl ReduceAnn) -> Bool isModule i (ModDecl n _ _ _ _) = i == n modInstActive :: [(ModDecl ReduceAnn)] -> (ModItem ReduceAnn) -> [Identifier] -modInstActive decl (ModInst n _ i) = case m of +modInstActive decl (ModInst n _ _ i) = case m of Nothing -> [] Just m' -> concat $ calcActive m' <$> zip i [0 ..] where @@ -308,9 +308,9 @@ modInstActive decl (ModInst n _ i) = case m of modInstActive _ _ = [] fixModInst :: (SourceInfo ReduceAnn) -> (ModItem ReduceAnn) -> (ModItem ReduceAnn) -fixModInst (SourceInfo _ (Verilog decl)) (ModInst n g i) = case m of +fixModInst (SourceInfo _ (Verilog decl)) (ModInst n p g i) = case m of Nothing -> error "Moditem not found" - Just m' -> ModInst n g . mapMaybe (fixModInst' m') $ zip i [0 ..] + Just m' -> ModInst n p g . mapMaybe (fixModInst' m') $ zip i [0 ..] where m = safe head $ filter (isModule n) decl fixModInst' (ModDecl _ o i' _ _) (ModConn e, n') @@ -391,7 +391,7 @@ halveAlways a = Single a -- | Check if a mod instance is in the current context. validModInst :: [Identifier] -> (ModItem ReduceAnn) -> Bool -validModInst ids (ModInst i _ _) = i `elem` ids +validModInst ids (ModInst i _ _ _) = i `elem` ids validModInst _ _ = True -- | Clean all the undefined module instances in a specific module using a diff --git a/src/Verismith/Verilog/AST.hs b/src/Verismith/Verilog/AST.hs index ca0d380..b30688d 100644 --- a/src/Verismith/Verilog/AST.hs +++ b/src/Verismith/Verilog/AST.hs @@ -663,6 +663,7 @@ data ModItem a = ModCA {_modContAssign :: !ContAssign} | ModInst { _modInstId :: {-# UNPACK #-} !Identifier, + _modInstDecl :: [ModConn], _modInstName :: {-# UNPACK #-} !Identifier, _modInstConns :: [ModConn] } @@ -687,7 +688,7 @@ instance Functor ModItem where fmap f (Initial s) = Initial $ fmap f s fmap f (Always s) = Always $ fmap f s fmap _ (ModCA c) = ModCA c - fmap _ (ModInst a b c) = ModInst a b c + fmap _ (ModInst a b c d) = ModInst a b c d fmap _ (Decl a b c) = Decl a b c fmap _ (ParamDecl p) = ParamDecl p fmap _ (LocalParamDecl l) = LocalParamDecl l @@ -726,8 +727,8 @@ traverseModConn f (ModConnNamed a e) = ModConnNamed a <$> f e traverseModItem :: (Applicative f) => (Expr -> f Expr) -> (ModItem ann) -> f (ModItem ann) traverseModItem f (ModCA (ContAssign a e)) = ModCA . ContAssign a <$> f e -traverseModItem f (ModInst a b e) = - ModInst a b <$> sequenceA (traverseModConn f <$> e) +traverseModItem f (ModInst a b c e) = + ModInst a b c <$> sequenceA (traverseModConn f <$> e) traverseModItem _ e = pure e -- | The complete sourcetext for the Verilog module. diff --git a/src/Verismith/Verilog/CodeGen.hs b/src/Verismith/Verilog/CodeGen.hs index 3c5d4c5..9c7a6da 100644 --- a/src/Verismith/Verilog/CodeGen.hs +++ b/src/Verismith/Verilog/CodeGen.hs @@ -113,10 +113,11 @@ portDir PortInOut = "inout" -- | Generate a '(ModItem ann)'. moduleItem :: Show ann => ModItem ann -> Doc a moduleItem (ModCA ca) = contAssign ca -moduleItem (ModInst i name conn) = +moduleItem (ModInst i param name conn) = (<> semi) $ hsep [ identifier i, + "#" <> (parens . hsep $ punctuate comma (mConn <$> param)), identifier name, parens . hsep $ punctuate comma (mConn <$> conn) ] diff --git a/src/Verismith/Verilog/Distance.hs b/src/Verismith/Verilog/Distance.hs index edc24f5..52d744a 100644 --- a/src/Verismith/Verilog/Distance.hs +++ b/src/Verismith/Verilog/Distance.hs @@ -142,7 +142,7 @@ instance Distance (Statement a) where instance Distance (ModItem a) where distance (ModCA _) (ModCA _) = 0 - distance (ModInst _ _ _) (ModInst _ _ _) = 0 + distance (ModInst _ _ _ _) (ModInst _ _ _ _) = 0 distance (Initial _) (Initial _) = 0 distance (Always s1) (Always s2) = distance s1 s2 distance (Decl _ _ _) (Decl _ _ _) = 0 diff --git a/src/Verismith/Verilog/Internal.hs b/src/Verismith/Verilog/Internal.hs index d06fc5f..ce4cbce 100644 --- a/src/Verismith/Verilog/Internal.hs +++ b/src/Verismith/Verilog/Internal.hs @@ -62,6 +62,7 @@ testBench = wireDecl "c", ModInst "and" + [] "and_gate" [ModConn $ Id "c", ModConn $ Id "a", ModConn $ Id "b"], Initial $ diff --git a/src/Verismith/Verilog/Mutate.hs b/src/Verismith/Verilog/Mutate.hs index 0855000..30359aa 100644 --- a/src/Verismith/Verilog/Mutate.hs +++ b/src/Verismith/Verilog/Mutate.hs @@ -128,7 +128,7 @@ instance Mutate LocalParam where instance Mutate (ModItem ann) where mutExpr f (ModCA (ContAssign a e)) = ModCA . ContAssign a $ f e - mutExpr f (ModInst a b conns) = ModInst a b $ mutExpr f conns + mutExpr f (ModInst a params b conns) = ModInst a (mutExpr f params) b $ mutExpr f conns mutExpr f (Initial s) = Initial $ mutExpr f s mutExpr f (Always s) = Always $ mutExpr f s mutExpr f (ModItemAnn a s) = ModItemAnn a $ mutExpr f s @@ -244,7 +244,7 @@ instantiateMod m main = main & modItems %~ ((out ++ regIn ++ [inst]) ++) <*> pure Nothing inst = ModInst - (m ^. modId) + (m ^. modId) [] (m ^. modId <> (Identifier . showT $ count + 1)) conns count = @@ -263,7 +263,7 @@ instantiateMod m main = main & modItems %~ ((out ++ regIn ++ [inst]) ++) -- m m(y, x); -- instantiateMod_ :: (ModDecl ann) -> (ModItem ann) -instantiateMod_ m = ModInst (m ^. modId) (m ^. modId) conns +instantiateMod_ m = ModInst (m ^. modId) [] (m ^. modId) conns where conns = ModConn @@ -278,7 +278,7 @@ instantiateMod_ m = ModInst (m ^. modId) (m ^. modId) conns -- m m(.y(y), .x(x)); -- instantiateModSpec_ :: Text -> (ModDecl ann) -> (ModItem ann) -instantiateModSpec_ outChar m = ModInst (m ^. modId) (m ^. modId) conns +instantiateModSpec_ outChar m = ModInst (m ^. modId) [] (m ^. modId) conns where conns = zipWith ModConnNamed ids (Id <$> instIds) ids = filterChar outChar (name modOutPorts) <> name modInPorts diff --git a/src/Verismith/Verilog/Parser.hs b/src/Verismith/Verilog/Parser.hs index 3a42c3c..80996ba 100644 --- a/src/Verismith/Verilog/Parser.hs +++ b/src/Verismith/Verilog/Parser.hs @@ -224,6 +224,16 @@ prefix name fun = Prefix ((tok name "prefix") >> return fun) commaSep :: Parser a -> Parser [a] commaSep = flip sepBy $ tok SymComma +toNE :: Parser [a] -> Parser (NonEmpty a) +toNE p = do + p' <- p + case p' of + a : b -> return $ a :| b + _ -> fail "List is empty." + +commaSepNE :: Parser a -> Parser (NonEmpty a) +commaSepNE = toNE . commaSep + parseContAssign :: Parser ContAssign parseContAssign = do var <- tok KWAssign *> identifier @@ -347,6 +357,22 @@ parseLoop = do statement <- parseStatement return $ ForLoop a expr incr statement +parseDefaultPair :: Parser (Statement a) +parseDefaultPair = tok' KWDefault *> tok' SymColon *> parseStatement + +parseCasePair :: Parser (CasePair ann) +parseCasePair = do + expr <- parseExpr <* tok' SymColon + CasePair expr <$> parseStatement + +parseCase :: Parser (Statement ann) +parseCase = do + expr <- tok' KWCase *> parseExpr + cp <- manyTill parseCasePair (lookAhead ((parseDefaultPair $> ()) <|> tok' KWEndcase)) + def <- option Nothing $ Just <$> parseDefaultPair + tok' KWEndcase + return (StmntCase CaseStandard expr cp def) + eventList :: TokenName -> Parser [Event] eventList t = do l <- sepBy parseEvent' (tok t) @@ -354,14 +380,11 @@ eventList t = do parseEvent :: Parser Event parseEvent = - tok' SymAtAster - $> EAll + (tok' SymAtAster $> EAll) <|> try (tok' SymAt *> tok' SymParenLAsterParenR $> EAll) <|> try ( tok' SymAt - *> tok' SymParenL - *> tok' SymAster - *> tok' SymParenR + *> parens (tok' SymAster) $> EAll ) <|> try (tok' SymAt *> parens parseEvent') @@ -410,6 +433,7 @@ parseStatement = parseSeq <|> parseConditional <|> parseLoop + <|> parseCase <|> parseEventCtrl <|> parseDelayCtrl <|> try parseBlocking @@ -437,10 +461,30 @@ parseModConn = try (fmap ModConn parseExpr) <|> namedModConn parseModInst :: Parser (ModItem ann) parseModInst = do m <- identifier + params <- option [] $ tok' SymPound *> parens (commaSep parseModConn) name <- identifier modconns <- parens (commaSep parseModConn) tok' SymSemi - return $ ModInst m name modconns + return $ ModInst m params name modconns + +parseParam :: Parser Parameter +parseParam = do + i <- tok' KWParameter *> identifier + expr <- tok' SymEq *> parseConstExpr + return $ Parameter i expr + +parseParam' :: Parser Parameter +parseParam' = do + i <- identifier + expr <- tok' SymEq *> parseConstExpr + return $ Parameter i expr + +parseParams :: Parser [Parameter] +parseParams = tok' SymPound *> parens (commaSep parseParam) + +parseParamDecl :: Parser (ModItem ann) +parseParamDecl = + ParamDecl <$> (tok' KWParameter *> commaSepNE parseParam' <* tok' SymSemi) parseModItem :: Parser (ModItem ann) parseModItem = @@ -449,6 +493,7 @@ parseModItem = <|> parseAlways <|> parseInitial <|> parseModInst + <|> parseParamDecl parseModList :: Parser [Identifier] parseModList = list <|> return [] where list = parens $ commaSep identifier @@ -460,15 +505,6 @@ filterDecl _ _ = False modPorts :: PortDir -> [ModItem ann] -> [Port] modPorts p mis = filter (filterDecl p) mis ^.. traverse . declPort -parseParam :: Parser Parameter -parseParam = do - i <- tok' KWParameter *> identifier - expr <- tok' SymEq *> parseConstExpr - return $ Parameter i expr - -parseParams :: Parser [Parameter] -parseParams = tok' SymPound *> parens (commaSep parseParam) - parseModDecl :: Parser (ModDecl ann) parseModDecl = do name <- tok KWModule *> identifier diff --git a/src/Verismith/Verilog/Preprocess.hs b/src/Verismith/Verilog/Preprocess.hs index 909334b..56c3e2c 100644 --- a/src/Verismith/Verilog/Preprocess.hs +++ b/src/Verismith/Verilog/Preprocess.hs @@ -28,6 +28,7 @@ uncomment file = uncomment' "" -> "" '/' : '/' : rest -> " " ++ removeEOL rest '/' : '*' : rest -> " " ++ remove rest + '(' : '*' : ')' : rest -> '(' : '*' : ')' : rest ++ remove rest '(' : '*' : rest -> " " ++ remove rest '"' : rest -> '"' : ignoreString rest b : rest -> b : uncomment' rest @@ -92,6 +93,7 @@ preprocess env file content = "" : pp (head stack) (tail stack) env_ rest | otherwise -> error $ "`endif without associated `ifdef/`ifndef: " ++ file + "`timescale" : _ -> pp on stack env_ rest _ -> (if on then ppLine env_ a else "") : pp on stack env_ rest ppLine :: [(String, String)] -> String -> String -- cgit