<commit_before>{-# LANGUAGE TypeOperators, ConstraintKinds, FlexibleContexts, CPP #-}
{-# LANGUAGE ViewPatterns, PatternGuards, ParallelListComp, ScopedTypeVariables #-}

{-# OPTIONS_GHC -Wall #-}
----------------------------------------------------------------------
-- |
-- Module      :  Circat.Netlist
-- Copyright   :  (c) 2013 Tabula, Inc.
-- License     :  BSD3
-- 
-- Maintainer  :  <EMAIL>
-- Stability   :  experimental
-- 
-- Circuit to Netlist conversion
----------------------------------------------------------------------

#define StateMachine

-- TODO: Use Text.Printf to replace the awkward string formations in this
-- module.

module Circat.Netlist
  ( toNetlist, mk_module
  , genVHDL, V.ppModule
  , outV  -- phasing out
  , saveAsVerilog
  ) where

import Data.Monoid (mempty,(<>),mconcat)
import Control.Arrow (first)
import Data.Maybe (fromMaybe)
import Data.Map (Map)
import qualified Data.Map as M
import Text.Printf (printf)

import System.Directory (createDirectoryIfMissing)

import Circat.Circuit
  ( CompS(..), compOuts, compName, compOuts, tagged
  , Width, PinId, Bus(..),Name,DGraph,Report
  , (:>), GenBuses,unitize,mkGraph,unDelayName
  )

import Language.Netlist.AST
  ( Module(..), Decl(..), Expr(..), ExprLit (..), Bit(..), Range(..)
  , BinaryOp(..), UnaryOp(..), Ident, Range, Event(..), Edge(..), Stmt(..) )

import Language.Netlist.GenVHDL(genVHDL)
import Language.Netlist.GenVerilog(mk_module)
import qualified Language.Verilog as V

-- PinId description: width & name
type PinDesc = (Width,String)

-- type PinToWireDesc = (PinId,PinDesc) 

type PinMap = Map PinId PinDesc

-- Phasing out
outV :: GenBuses a => Name -> (a :> b) -> IO ()
outV name circ = saveVerilog name' (toVerilog ndr)
 where
   ndr@(name',_,_) = mkGraph name (unitize circ)

-- | Converts a Circuit to a Module
toNetlist :: Name -> DGraph -> Module

toNetlist name comps =
  Module name' (clockIns++ins) outs [] (nets++assigns++clockDecls)
 where
   (p2wIn,ins)    = modPorts "In"
   (_,outs)       = modPorts "Out"
   (p2wNets,nets) = moduleNets comps
   p2w            = p2wIn <> p2wNets
   assigns        = moduleAssigns p2w comps
   modPorts str   = modulePorts (portComp str comps)
   (clockIns,clockDecls) = clocked p2w comps
   name' = map tweak name
    where
      tweak '-' = '_'
      tweak c   = c

-- TODO: rename "portComp", since it's no longer just about module ports.

clocked :: PinMap -> DGraph -> ([(Ident,Maybe Range)],[Decl])
clocked p2w comps
  | null states = mempty
  | otherwise =
      ( [("clock",Nothing),("reset",Nothing)]
      , [ProcessDecl
           (Event (ExprVar "clock") PosEdge) Nothing
           (If (ExprBinary Equals
                 (ExprVar "reset") (ExprLit Nothing (ExprBit T)))
               (updates starts)
               (Just (updates news)))] )
 where
  starts,news,states :: [Expr]
  (starts,news,states) =
    unzip3 [ (start,var new,var state)
           | CompS _ (delayStart -> Just start) [new] [state] _ <- comps]
  var :: Bus -> Expr
  var = sourceExp p2w  -- Move to view pattern
  updates :: [Expr] -> Stmt
  updates sources = sseq (zipWith Assign states sources)

delayStart :: Name -> Maybe Expr
delayStart = fmap readLitExpr . unDelayName

readLitExpr :: String -> Expr<commit_msg>withReset<commit_after>{-# LANGUAGE TypeOperators, ConstraintKinds, FlexibleContexts, CPP #-}
{-# LANGUAGE ViewPatterns, PatternGuards, ParallelListComp, ScopedTypeVariables #-}

{-# OPTIONS_GHC -Wall #-}
----------------------------------------------------------------------
-- |
-- Module      :  Circat.Netlist
-- Copyright   :  (c) 2013 Tabula, Inc.
-- License     :  BSD3
-- 
-- Maintainer  :  <EMAIL>
-- Stability   :  experimental
-- 
-- Circuit to Netlist conversion
----------------------------------------------------------------------

-- TODO: Use Text.Printf to replace the awkward string formations in this
-- module.

module Circat.Netlist
  ( toNetlist, mk_module
  , genVHDL, V.ppModule
  , outV  -- phasing out
  , saveAsVerilog
  ) where

import Data.Monoid (mempty,(<>),mconcat)
import Control.Arrow (first)
import Data.Maybe (fromMaybe)
import Data.Map (Map)
import qualified Data.Map as M
import Text.Printf (printf)

import System.Directory (createDirectoryIfMissing)

import Circat.Circuit
  ( CompS(..), compOuts, compName, compOuts, tagged
  , Width, PinId, Bus(..),Name,DGraph,Report
  , (:>), GenBuses,unitize,mkGraph,unDelayName
  )

import Language.Netlist.AST
  ( Module(..), Decl(..), Expr(..), ExprLit (..), Bit(..), Range(..)
  , BinaryOp(..), UnaryOp(..), Ident, Range, Event(..), Edge(..), Stmt(..) )

import Language.Netlist.GenVHDL(genVHDL)
import Language.Netlist.GenVerilog(mk_module)
import qualified Language.Verilog as V

-- PinId description: width & name
type PinDesc = (Width,String)

-- type PinToWireDesc = (PinId,PinDesc) 

type PinMap = Map PinId PinDesc

-- Phasing out
outV :: GenBuses a => Name -> (a :> b) -> IO ()
outV name circ = saveVerilog name' (toVerilog ndr)
 where
   ndr@(name',_,_) = mkGraph name (unitize circ)

-- | Converts a Circuit to a Module
toNetlist :: Name -> DGraph -> Module
toNetlist name comps =
  Module name' (clockIns++ins) outs [] (nets++assigns++clockDecls)
 where
   (p2wIn,ins)    = modPorts "In"
   (_,outs)       = modPorts "Out"
   (p2wNets,nets) = moduleNets comps
   p2w            = p2wIn <> p2wNets
   assigns        = moduleAssigns p2w comps
   modPorts str   = modulePorts (portComp str comps)
   (clockIns,clockDecls) = clocked p2w comps
   name' = map tweak name
    where
      tweak '-' = '_'
      tweak c   = c

-- TODO: rename "portComp", since it's no longer just about module ports.

-- Whether to handle dynamic reset.
withReset :: Bool
withReset = True

clocked :: PinMap -> DGraph -> ([(Ident,Maybe Range)],[Decl])
clocked p2w comps
  | null states = mempty
  | otherwise =
      ( ("clock",Nothing) : if withReset then [("reset",Nothing)] else []
      , [ProcessDecl
           (Event (ExprVar "clock") PosEdge) Nothing
           (if withReset then
             If (ExprBinary Equals
                  (ExprVar "reset") (ExprLit Nothing (ExprBit T)))
                (updates starts)
                (Just (updates news))
            else
              updates news)] )
 where
  starts,news,states :: [Expr]
  (starts,news,states) =
    unzip3 [ (start,var new,var state)
           | CompS _ (delayStart -> Just start) [new] [state] _ <- comps]
  var :: Bus -> Expr
  var = sourceExp p2w  -- Move to view pattern
  updates :: [Expr] -> Stmt
  updates sources = sseq (zipWith Assign states sources)

delayStart :: Name -> Maybe Expr
delayStart = fmap readLitExpr . unDelayName

readLitExpr :: String -> Expr
{'fraction_non_alphanumeric': 0.17138152971112108, 'fraction_numerical': 0.00449034575662326, 'mean_word_length': 2.5770877944325483, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 37, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2843640', 'n_tokens_mistral': 2250, 'n_tokens_neox': 2196, 'n_words': 605}