module Export.DEF
( exportDEF
) where
import qualified Data.Map as Map
import qualified Data.Foldable as Fold
import Data.List
import Data.String
import Data.Hardware.Internal
import Lava.Internal
import Layout.Internal
import Wired.Model
type ComponentDEF =
( CellId
, Name
, Position
, Orientation
)
type NetDEF =
( Name
, [(CellId, Name)]
, [(Layer_, Position, Position)]
, [Tag]
)
type ExportDEF =
( Name
, Name
)
showPos :: Position -> ShowS
showPos (x,y) = unwordS
[ "("
, shows x'
, shows y'
, ")"
]
where
x' = round (value x / 1e-9) :: Integer
y' = round (value y / 1e-9) :: Integer
showOri :: IsString str => Orientation -> str
showOri (flipped,dir) = fromString $
(if flipped then "F" else "") ++ showDir dir
where
showDir Rightwards = "E"
showDir Leftwards = "W"
showDir Upwards = "N"
showDir Downwards = "S"
top title (x,y) =
"VERSION 5.5 ; \n\
\NAMESCASESENSITIVE ON ; \n\
\DIVIDERCHAR \"/\" ; \n\
\BUSBITCHARS \"[]\" ; \n\
\DESIGN " .+ title .+ " ; \n\
\DIEAREA ( 0 0 ) " .+ showPos topRight .+ " ; \n\
\UNITS DISTANCE MICRONS 1000 ; \n\
\ \n"
where
topRight = (addLen x (x`divLen`5), addLen y (y`divLen`5))
renderDEF
:: [ComponentDEF]
-> [NetDEF]
-> [ExportDEF]
-> [ExportDEF]
-> [ExportDEF]
-> Position -> Name -> IO ()
renderDEF comps nets iExps oExps ioExps topRight title
= writeFile (title ++ ".def")
$ top (showString title) topRight
.+ wrapper "COMPONENTS" (length comps) (map renderComp comps)
.+ wrapper "NETS" (length nets) (map renderNet nets)
.+ wrapper "PINS" lExps renderExports
$ "END DESIGN\n"
where
wrapper kind n lines = unlineS
$ [kind .+ " " .+ shows n .+ " ;"]
++ lines
++ ["END " .+ kind .+ "\n\n"]
renderComp (nid, nm, pos, ori) = unwordS
[ "- CELL" .+ shows (toInt nid)
, showString nm
, "+ PLACED"
, showPos pos
, showOri ori .+ " ;"
]
renderNet (nm,ps,gs,ts) = unwordS
$ ["- " .+ showString nm]
++ map renderPin ps
++ [";"]
++ tags
where
tags = if null ts then [] else "#" : map showString ts
renderPin (nid,cnm) = unwordS
[ "( CELL" .+ shows (toInt nid), showString cnm, ")" ]
renderGuide (lay,pos1,pos2)
= "+ ROUTED M"
.+ shows (toInt lay)
.+ " " .+ showPos pos1
.+ if pos1==pos2
then ""
else " " .+ showPos pos2
lExps = length (iExps++oExps++ioExps)
iExps' = zip iExps (repeat "INPUT")
oExps' = zip oExps (repeat "OUTPUT")
ioExps' = zip ioExps (repeat "INOUT")
renderExports = map renderExport $ zip [0..] (iExps'++oExps'++ioExps')
renderExport (p,((pinName,netName),dir)) = unwordS
[ "- " .+ showString pinName
, "+ NET " .+ showString netName
, "+ DIRECTION"
, dir
, ";"
]
exportDEF
:: (CellLibrary lib, Port p Signal)
=> Name -> Wired lib p -> IO ()
exportDEF title wp =
renderDEF compsDEF netsDEF iExpsDEF oExpsDEF ioExpsDEF topRight title
where
(p,(db,fp)) = runWired wp
(afp,topRight) = absolutize fp
cellType = fst . (cellDB db Map.!)
netName (PrimInpSig iid) = "inp" ++ show (toInt iid)
netName (CellSig cid pin) =
"sig" ++ show (toInt cid) ++ "-" ++ show (toInt pin)
compsDEF = [ (cid,nm,pos,ori) | (pos, Box _ ori nm cid) <- afp ]
netsDEF = do
(driver,loads) <- Map.toList $ fanoutDB db
let net = mkNet driver loads
gs = totalLookup driver (mkGuideDB fp)
ts = totalLookup driver (sigTagDB db)
return (netName driver, net ,gs, ts)
where
mkNet driver loads
= driverPin
++ [ (cid, inPinName (cellType cid) pin) | (cid,pin) <- loads ]
where
driverPin = case driver of
PrimInpSig _ -> []
CellSig cid pin -> [(cid, outPinName (cellType cid) pin)]
filterInps is = [i | i <- is, not $ null $ totalLookup i $ fanoutDB db]
isInput (PrimInpSig _) = True
isInput _ = False
(ios_,os) = partition isInput $ Fold.toList (port p)
ios = filterInps ios_
is = filterInps (primIns db) \\ ios
expName pre n sig
= concat
$ intersperse "_"
$ ((pre++show n):)
$ totalLookup sig
$ sigTagDB db
listExports typ ss =
[(expName typ n s, netName s) | (n,s) <- [0..] `zip` ss]
iExpsDEF = listExports "in" is
oExpsDEF = listExports "out" os
ioExpsDEF = listExports "inout" ios