a functional-logic library for wired matthew naylor and collin runciman – university of york emil...

37
A Functional-Logic Library for Wired Matthew Naylor and Collin Runciman – University of York Emil Axelsson – Chalmers University Haskell Workshop 2007

Upload: noah-logan

Post on 31-Dec-2015

220 views

Category:

Documents


2 download

TRANSCRIPT

Page 1: A Functional-Logic Library for Wired Matthew Naylor and Collin Runciman – University of York Emil Axelsson – Chalmers University Haskell Workshop 2007

A Functional-Logic Library for Wired

A Functional-Logic Library for Wired

Matthew Naylor and Collin Runciman – University of York

Emil Axelsson – Chalmers University

Haskell Workshop 2007

Page 2: A Functional-Logic Library for Wired Matthew Naylor and Collin Runciman – University of York Emil Axelsson – Chalmers University Haskell Workshop 2007

Acknowledgement

This project recieves Intel-custom funding from the Semiconductor Research Corporation

Page 3: A Functional-Logic Library for Wired Matthew Naylor and Collin Runciman – University of York Emil Axelsson – Chalmers University Haskell Workshop 2007

Overview

Background: Digital circuit design

Wired: Low-level hardware design in Haskell

LP: Logic programming in Haskell

Wired implemented using LP

Page 4: A Functional-Logic Library for Wired Matthew Naylor and Collin Runciman – University of York Emil Axelsson – Chalmers University Haskell Workshop 2007

Circuit abstraction levels

Just like software, digital circuits can be described at various levels of abstraction:

Netlist: Directed graph with simple Boolean gates as nodes

Placed netlist: Netlist where every gate has been assigned a unique position on the chip

Final layout: Placed netlist where every connection has been assigned a unique route in the metal layers

Netlist-to-layout is normally done by automatic tools

Page 5: A Functional-Logic Library for Wired Matthew Naylor and Collin Runciman – University of York Emil Axelsson – Chalmers University Haskell Workshop 2007

The problem…

Integrated circuit performance is largely determined by wire properties

Long wire longer signal delay, more power dissipationMany long wires bigger chip area

The abstract netlist view leaves wires implicit!

Conclusion: Hard to reason about performance at the netlist level

Evidence: Large parts of Intel’s chips are designed through manual layout editing

Page 6: A Functional-Logic Library for Wired Matthew Naylor and Collin Runciman – University of York Emil Axelsson – Chalmers University Haskell Workshop 2007

Can Haskell help?

Haskell has already proven to be useful for hardware description at the (placed) netlist level (Lava, Hydra)

Idea: Take the Lava approach further and describe the full layout, including wiring in Haskell

Result: Wired

Page 7: A Functional-Logic Library for Wired Matthew Naylor and Collin Runciman – University of York Emil Axelsson – Chalmers University Haskell Workshop 2007

Wired example

bitMult = row (and2 *=* wiring) where wiring = (wire *||* wireT0 *||* wire) `withConstraintW` (<== sigStruct)

Netlist and layout

described simultaneously

Netlist and layout

described simultaneously

Wires and gates are conceptually the same

thing!

Wires and gates are conceptually the same

thing!

Page 8: A Functional-Logic Library for Wired Matthew Naylor and Collin Runciman – University of York Emil Axelsson – Chalmers University Haskell Workshop 2007

Functional circuit model

Lava represents circuits as functions

Inputs and outputs are determined syntactically

But where is the input here?

Page 9: A Functional-Logic Library for Wired Matthew Naylor and Collin Runciman – University of York Emil Axelsson – Chalmers University Haskell Workshop 2007

Relational circuit model

One relational combinator captures a whole family of functional ones (signal-flow abstraction)

Page 10: A Functional-Logic Library for Wired Matthew Naylor and Collin Runciman – University of York Emil Axelsson – Chalmers University Haskell Workshop 2007

Relational circuit model

One relational wire captures a whole family of functional ones (signal-flow abstraction)

Page 11: A Functional-Logic Library for Wired Matthew Naylor and Collin Runciman – University of York Emil Axelsson – Chalmers University Haskell Workshop 2007

Relational circuit model

Size inference

x

64

Page 12: A Functional-Logic Library for Wired Matthew Naylor and Collin Runciman – University of York Emil Axelsson – Chalmers University Haskell Workshop 2007

LP: Logic programming in Haskell

Old Wired implementation very ad-hoc and inefficient

Matthew Naylor spotted that Curry was better suited for implementing Wired

This led to the birth of the library LPInspired by Curry and Typed logical variables in Haskell. Claessen and Ljunglöf (HW’2000)Easy construction/deconstruction of logical termsSupports residuation (heavily used in Wired)Supports non-determinism

Page 13: A Functional-Logic Library for Wired Matthew Naylor and Collin Runciman – University of York Emil Axelsson – Chalmers University Haskell Workshop 2007

Logical terms

data Uni = Var VarID | Ctr Int [Uni] | Int Int

newtype Term a = Term { uni :: Uni }

type VarID = Int

nil :: Term [a]nil = Term (Ctr 0 [])

(|>) :: Term a -> Term [a] -> Term [a]a |> as = Term (Ctr 1 [uni a, uni as])

int :: Int -> Term Intint n = Term (Int n)...

Definition

Constructors

Page 14: A Functional-Logic Library for Wired Matthew Naylor and Collin Runciman – University of York Emil Axelsson – Chalmers University Haskell Workshop 2007

Automating data type creation

(nil ::: (|>)) = datatype (cons0 [] \/ cons2 (:))

(true ::: false) = datatype (cons0 True \/ cons0 False)

Page 15: A Functional-Logic Library for Wired Matthew Naylor and Collin Runciman – University of York Emil Axelsson – Chalmers University Haskell Workshop 2007

Logic programs

data LP a = LP { runLP :: State -> [(a, State)] }

type State = (Map VarID Val, VarID)

type Residual = Uni -> LP ()data Val = Bound Uni | Unbound [Residual]

Possibly bound to a

term

Possibly bound to a

term

Current variable mapping, and a

fresh ID

Current variable mapping, and a

fresh ID

Non-determinism + stateNon-determinism + state

Actual implementation uses Hinze’s two-continuation monad transformer and

IORef’s

Actual implementation uses Hinze’s two-continuation monad transformer and

IORef’s

Page 16: A Functional-Logic Library for Wired Matthew Naylor and Collin Runciman – University of York Emil Axelsson – Chalmers University Haskell Workshop 2007

Basic LP interface

instance Monad LP ...

instance MonadPlus LP ...

(?) :: LP a -> LP a -> LP a(?) = mplus

newVar :: Val -> LP VarID

readVar :: VarID -> LP Val

writeVar :: VarID -> Val -> LP ()

(>>) interpreted as conjunction

(>>) interpreted as conjunction

Disjunction + failure

Disjunction + failure

Page 17: A Functional-Logic Library for Wired Matthew Naylor and Collin Runciman – University of York Emil Axelsson – Chalmers University Haskell Workshop 2007

Unification

unify :: Uni -> Uni -> LP ()unify a b = do ra <- root a; rb <- root b unif ra rb where unif (Var v) (Var w) | v == w = return () unif (Var v) b = bindVar v b unif a (Var w) = bindVar w a unif (Int a) (Int b) | a == b = return () unif (Ctr n as) (Ctr m bs) | n == m = unif' as bs unif _ _ = mzero

unif' [] [] = return () unif' (a:as) (b:bs) = unify a b >> unif' as bs

Page 18: A Functional-Logic Library for Wired Matthew Naylor and Collin Runciman – University of York Emil Axelsson – Chalmers University Haskell Workshop 2007

Logical class

class Logical a where free :: LP a (===) :: a -> a -> LP ()

instance Logical (Term a) where free = return . Term . Var =<< unboundVar a === b = unify (uni a) (uni b)

instance (Logical a, Logical b) => Logical (a,b) where free = liftM2 (,) free free (a0,a1) === (b0,b1) = a0 === b0 >> a1 === b1

Page 19: A Functional-Logic Library for Wired Matthew Naylor and Collin Runciman – University of York Emil Axelsson – Chalmers University Haskell Workshop 2007

Example: Append

app :: Term [a] -> Term [a] -> Term [a] -> LP ()

app as bs cs = do as===nil bs===cs ? do ((a,as'),cs’) <- free a|>as' === as a|>cs' === cs app as' bs cs'

testApp = run $ do as' <- free let as = 1|>2|>3|> as' cs = 1|>2|>3|>4|>5|> nil bs <- free app as bs cs return bs

*Main> testApp [[4,5],[5],[]]

Page 20: A Functional-Logic Library for Wired Matthew Naylor and Collin Runciman – University of York Emil Axelsson – Chalmers University Haskell Workshop 2007

Pattern matching

pat --> rhs = return (pat,rhs)

caseOf a as = do (pat,rhs) <- free >>= as pat === a rhs

app as bs cs = caseOf (as,cs) alts where alts ((a,as'),cs')

= (nil,cs') --> (bs===cs) ? (a|>as', a|>cs') --> app as' bs cs'

Page 21: A Functional-Logic Library for Wired Matthew Naylor and Collin Runciman – University of York Emil Axelsson – Chalmers University Haskell Workshop 2007

Residuation

rigid :: Logical b => (Uni -> LP b) -> (Uni -> LP b)...

Does not accept variables

(pure function)

Does not accept variables

(pure function)

Accepts variablesAccepts variables

Page 22: A Functional-Logic Library for Wired Matthew Naylor and Collin Runciman – University of York Emil Axelsson – Chalmers University Haskell Workshop 2007

Residuation

rigid :: Logical b => (Uni -> LP b) -> (Uni -> LP b)...

data Val = Bound Uni | Unbound [Residual]type Residual = Uni -> LP ()

bindVar :: VarID -> Uni -> LP ()bindVar v a = do Unbound rs <- readVar v writeVar v (Bound a) rs `resumeOn` a

Used by unify to instantiate a variable

Used by unify to instantiate a variable

Page 23: A Functional-Logic Library for Wired Matthew Naylor and Collin Runciman – University of York Emil Axelsson – Chalmers University Haskell Workshop 2007

Rigid deconstruction/arithmetic

unint :: Logical b => Term Int -> (Int -> LP b) -> LP bunint a f = rigid (\(Int a) -> f a) (uni a)

liftInt2 f a b = unint a (\a -> unint b (\b -> return (int (f a b))))

(|+|), (|-|), (|*|) :: Term Int -> Term Int -> LP (Term Int)

(|+|) = liftInt2 (+)(|-|) = liftInt2 (-)(|*|) = liftInt2 (*)

Page 24: A Functional-Logic Library for Wired Matthew Naylor and Collin Runciman – University of York Emil Axelsson – Chalmers University Haskell Workshop 2007

Residuation example

(<==) :: Logical a => a -> LP a -> LP ()a <== m = (a===) =<< m

testResid = run $ do (res,x) <- free res <== x |-| 3 x <== 5 |*| 2 return res

*Main> testResid [7]

Page 25: A Functional-Logic Library for Wired Matthew Naylor and Collin Runciman – University of York Emil Axelsson – Chalmers University Haskell Workshop 2007

Determistic relations

a <+> b = do c <- a |+| b b <== c |-| a a <== c |-| b return c

testPlus = run $ do a <- free 20 <== ((1<+>) =<< (2<+>) =<< (3<+>a)) return a

*Main> testPlus[14]

If any two of a, b and c are known, the third one will be

inferred

If any two of a, b and c are known, the third one will be

inferred

• Completely deterministic• Abstract information flow

Exactly what Wired needs!

• Completely deterministic• Abstract information flow

Exactly what Wired needs!

Page 26: A Functional-Logic Library for Wired Matthew Naylor and Collin Runciman – University of York Emil Axelsson – Chalmers University Haskell Workshop 2007

Wired

n

w

s

e

data Circuit w n s e = Circ { west :: w , north :: n , south :: s , east :: e , sizeX :: Term Size , sizeY :: Term Size , layout :: Term Layout }

type Circ w n s e = LP (Circuit w n s e)

Ports :Contain geometry

and signals of each side

Ports :Contain geometry

and signals of each side

Page 27: A Functional-Logic Library for Wired Matthew Naylor and Collin Runciman – University of York Emil Axelsson – Chalmers University Haskell Workshop 2007

Wired: Below composition

(*=*) :: (...) => Circ wL x sL eL -> Circ wH nH x eH -> Circ (wL,wH) nH sL (eL,eH)

circL *=* circH = do Circ wL nL sL eL szxL szyL layL <- circL Circ wH nH sH eH szxH szyH layH <- circH

nL === sH szy <- szyL <+> szyH let lay = (term (layL :=: layH))

return $ Circ (wL,wH) nH sL (eL,eH) szxL szy lay

nL

wL

sL

eL

nH

wH

sL

eH

sL

nH

(wL,wH)

(eL,eH)

Connects netlists and exchanges geometrical info

Connects netlists and exchanges geometrical info

*=*

Page 28: A Functional-Logic Library for Wired Matthew Naylor and Collin Runciman – University of York Emil Axelsson – Chalmers University Haskell Workshop 2007

Size inference revisited

x

64

Page 29: A Functional-Logic Library for Wired Matthew Naylor and Collin Runciman – University of York Emil Axelsson – Chalmers University Haskell Workshop 2007

Connection pattern: row

rowN :: (...) => Term Int -> Circ x n s x -> Circ x [n] [s] xrowN n circ = unint n rowNN where rowNN 0 = nilY rowNN n = circ *||~ rowNN (n-1)

row :: (...) => Circ y n s y -> Circ y [n] [s] yrow circ = do cR <- free l <- lengthR (north cR) l <== lengthR (south cR) cR <== rowN l circ return cR

Length determined by context.

lengthR is a rigid version of length.

Length determined by context.

lengthR is a rigid version of length.

Page 30: A Functional-Logic Library for Wired Matthew Naylor and Collin Runciman – University of York Emil Axelsson – Chalmers University Haskell Workshop 2007

Bit multiplier revisited

bitMult = row (and2 *=* wiring) where wiring = (wire *||* wireT0 *||* wire) `withConstraintW` (<== sigStruct)

*Main> renderCircuit "circ" (bitMult `ofLengthX` 6)

Page 31: A Functional-Logic Library for Wired Matthew Naylor and Collin Runciman – University of York Emil Axelsson – Chalmers University Haskell Workshop 2007

Example: Sklansky

sklansky 0 op opFO = rowN 1 $ nilX `withConstraint` \c -> north c <== (structure =<< asLP south =<< op)

sklansky d op opFO = consW (joinL *=* skl) ~||~ consE (joinR *=* skl) where skl = sklansky (d-1) op opFO op' = op *=*alignLeft opFO' = opFO*=*alignLeft joinL = row (busY*=*busY) ~||* (busT1*=*busY) joinR = row opFO' ~||* op'

Page 32: A Functional-Logic Library for Wired Matthew Naylor and Collin Runciman – University of York Emil Axelsson – Chalmers University Haskell Workshop 2007

Example: Sklansky

*Main> renderCircuit "circ" $ sklansky 3 dot dotFO

Page 33: A Functional-Logic Library for Wired Matthew Naylor and Collin Runciman – University of York Emil Axelsson – Chalmers University Haskell Workshop 2007

Related work

Lava:

Claessen, Sheeran, Singh. CHARME’2001.

Logic programming in Haskell:

Typed logical variables in Haskell. Claessen and Ljunglöf, HW’2000.

Backtracking, interleaving and terminating monad transformers. Kiselyov, Shan, Friedman and Sabry, ICFP’2005.

SparseCheck (Matthew Naylor 2007)

Page 34: A Functional-Logic Library for Wired Matthew Naylor and Collin Runciman – University of York Emil Axelsson – Chalmers University Haskell Workshop 2007

Future work

LP:More forms of non-determinism (breadth-first, fair backtracking…)Lazy narrowing

Wired:Working on new much simplified version (might not need LP…)Producing real layout for evaluationExamples…

Page 35: A Functional-Logic Library for Wired Matthew Naylor and Collin Runciman – University of York Emil Axelsson – Chalmers University Haskell Workshop 2007

Unification

unboundVar :: LP VarIDunboundVar = newVar (Unbound [])

bindVar :: VarID -> Uni -> LP ()bindVar v a = writeVar v (Bound a)

ifBound :: VarID -> (Uni -> LP b) -> LP b -> LP bifBound v t f = readVar v >>= decons where decons (Bound a) = t a decons (Unbound _) = f

root :: Uni -> LP Uniroot (Var v) = ifBound v root (return (Var v))root a = return a

Page 36: A Functional-Logic Library for Wired Matthew Naylor and Collin Runciman – University of York Emil Axelsson – Chalmers University Haskell Workshop 2007

Residuation

rigid' :: Logical b => (Uni -> LP b) -> (Uni -> LP b)...

data Val = Bound Uni | Unbound [Residual]type Residual = Uni -> LP ()

bindVar :: VarID -> Uni -> LP ()bindVar v a = do Unbound rs <- readVar v writeVar v (Bound a) rs `resumeOn` a

resumeOn :: [Residual] -> Uni -> LP ()

resumeOn rs (Var v) = do Unbound ss <- readVar v writeVar v (Unbound (rs ++ ss))

resumeOn rs a = mapM_ (resume a) rs where resume a g = g aUsed by unify to

instantiate a variableUsed by unify to

instantiate a variable

Page 37: A Functional-Logic Library for Wired Matthew Naylor and Collin Runciman – University of York Emil Axelsson – Chalmers University Haskell Workshop 2007

Residuation

rigid' :: Logical b => (Uni -> LP b) -> (Uni -> LP b)

rigid' f a = do ar <- root a b <- free let g x = f x >>= (===b) [g] `resumeOn` ar return b

rigid :: Logical b => (Term a -> LP b) -> (Term a -> LP b)rigid f a = rigid' (f . Term) (uni a)

b gives access to the (future) result of the

computation

b gives access to the (future) result of the

computation