<!DOCTYPE article PUBLIC "-//NLM//DTD JATS (Z39.96) Journal Archiving and Interchange DTD v1.0 20120330//EN" "JATS-archivearticle1.dtd">
<article xmlns:xlink="http://www.w3.org/1999/xlink">
  <front>
    <journal-meta />
    <article-meta>
      <title-group>
        <article-title>Concurrency Oracles for Free</article-title>
      </title-group>
      <contrib-group>
        <contrib contrib-type="author">
          <string-name>Georgy Lukyanov</string-name>
          <xref ref-type="aff" rid="aff0">0</xref>
        </contrib>
        <contrib contrib-type="author">
          <string-name>Andrey Mokhov</string-name>
          <xref ref-type="aff" rid="aff0">0</xref>
        </contrib>
        <aff id="aff0">
          <label>0</label>
          <institution>School of Engineering, Newcastle University</institution>
          ,
          <country country="UK">United Kingdom</country>
        </aff>
      </contrib-group>
      <fpage>112</fpage>
      <lpage>127</lpage>
      <abstract>
        <p>This paper presents an approach to deriving concurrency oracles for processor instructions whose behaviour is formally specified using a state transformer semantics. The presented approach does not require any modification of the existing semantics, nor does it rely on writing a parser for the language in which the semantics is described, thus justifying the “for free” part of the title. The main tool in our arsenal is ad-hoc polymorphism: the presented approach is only applicable when the semantics of processor instructions is expressed using state transformation functions that can be reinterpreted in different contexts. As we show in the paper, such semantics can be interpreted not only for instruction simulation or verification, but also for extracting the information about instruction dependencies, thus allowing us to identify concurrency as well as various types of conflicts between instructions or blocks of instructions.</p>
      </abstract>
      <kwd-group>
        <kwd>concurrency oracle</kwd>
        <kwd>instruction set architecture</kwd>
        <kwd>functional programming</kwd>
        <kwd>polymorphism</kwd>
      </kwd-group>
    </article-meta>
  </front>
  <body>
    <sec id="sec-1">
      <title>Introduction and motivation</title>
      <p>
        Deciding whether two given events in a trace are concurrent, i.e. have no causal
or data dependencies between them, is a major problem in the process
discovery field [
        <xref ref-type="bibr" rid="ref3">3</xref>
        ]. Various methods for concurrency extraction, often referred to as
concurrency oracles, have been introduced, including the classic α-algorithm [
        <xref ref-type="bibr" rid="ref4">4</xref>
        ],
as well as a few less widely known methods, e.g. see [
        <xref ref-type="bibr" rid="ref7">7</xref>
        ], [
        <xref ref-type="bibr" rid="ref15">15</xref>
        ] and the review
paper [
        <xref ref-type="bibr" rid="ref5">5</xref>
        ]. A good example of treating a concurrency oracle as a self-contained
problem can be found in [
        <xref ref-type="bibr" rid="ref8">8</xref>
        ].
      </p>
      <p>In this paper we present an approach for deriving concurrency oracles for
events that correspond to processor instructions and blocks of instructions. The
input to the proposed approach is the microarchitectural semantics of
instructions, which gives a precise description of how an instruction execution changes
the state of the processor. We show how the presented approach can be applied
for program analysis and for synthesis of efficient hardware microcontrollers.</p>
      <p>
        A popular method to describe microarchitectural semantics is to use a
dedicated domain-specific language embedded in a high-level general-purpose host
language, such as Haskell or Coq. Two pioneering works in this domain are [
        <xref ref-type="bibr" rid="ref9">9</xref>
        ],
where the Arm v7 instruction set architecture is formalised in HOL4, and [
        <xref ref-type="bibr" rid="ref10">10</xref>
        ],
where x86 architecture is formalised in Coq.
      </p>
      <p>
        The authors of this paper have also used an embedded domain-specific
language to describe the semantics of a space-grade microarchitecture [
        <xref ref-type="bibr" rid="ref16">16</xref>
        ]. In
particular, it was demonstrated that the same semantics can be reused in different
contexts: to simulate the processor and to perform formal verification of
programs executed by the processor. In this paper we take this work further, by
demonstrating that the very same semantics can be reused for deriving
concurrency oracles that given two instructions, or blocks of instructions, can determine
whether they are concurrent and, if not, report the data dependency conflicts.
      </p>
      <p>We start by studying several common examples of processor instructions,
noticing that different instructions require different features from the language
used to describe them; see §2. We proceed by introducing the language for
specifying semantics in more detail and then describe the semantics of a small
instruction set (§3). The approach to deriving concurrency oracles is presented in §4.
Precise analysis of data dependencies between program instructions allows us to
synthesise efficient hardware controllers for executing predefined collections of
programs, as demonstrated in §5, followed by a discussion.
2</p>
    </sec>
    <sec id="sec-2">
      <title>Instruction set architecture semantics</title>
      <p>In this section we introduce a metalanguage for describing the semantics of
processor instructions by following a few examples. We will use the metalanguage to
describe the semantics of a part of a simple generic instruction set architecture.
The later sections will introduce a formal definition of the metalanguage,
instruction semantics and present a method for extracting static data dependencies of
instructions with certain properties from the semantic definitions leading to a
construction of a concurrency oracle. Fig. 1 shows three example dependency
graphs that can be automatically produced by the presented method.
Load Loading a data word from memory to a register is one of the simplest
processor instructions. Here is how1 we encode its semantics in our metalanguage:
load reg addr = \read write -&gt; Just $</p>
      <p>
        write (Reg reg) (read (Addr addr))
In this definition we use two metalanguage terms read and write to specify the
behaviour of the instruction, specifically to read the memory location at address
addr, and write the result into the register reg. Crucially, read and write are
polymorphic over the computational context f and have the following types:
read :: forall f. Key -&gt; f Value
write :: forall f. Key -&gt; f Value -&gt; f ()
Here Key is used to identify a particular component of the processor state, such
as a memory location or a register, and Value is the type of data the processor
operates on, e.g. Value for a 64-bit processor.
1 We use Haskell throughout the paper, not only because it is one of the most popular
functional programming languages, but also because it provides support for
higherrank polymorphism [
        <xref ref-type="bibr" rid="ref17">17</xref>
        ], which is essential for the presented approach.
      </p>
      <p>The read term queries the microarchitectural state for the value of a key
and returns it wrapped in a context f, which in this case captures the effect of
reading from the state. The write term takes a key and a value, and modifies the
microarchitectural state, returning no information (the unit ()), but capturing
the effect of writing in the context f.</p>
      <p>
        Addr 0
This instruction adds an offset to the instruction counter IC to transfer the
control to another instruction in the program. This definition has a crucial
difference from load: it uses the function &lt;$&gt; of the Functor type class4, thus
restricting f of the read and write terms to be a Functor:
read :: forall f. Functor f =&gt; Key -&gt; f Value
write :: forall f. Functor f =&gt; Key -&gt; f Value -&gt; f ()
3 We used the algebraic-graphs Haskell library [
        <xref ref-type="bibr" rid="ref14">14</xref>
        ] to export dependency graphs into
the DOT format, and then applied GraphViz [
        <xref ref-type="bibr" rid="ref18">18</xref>
        ] for automated layout.
4 Function &lt;$&gt; (pronounced “fmap”) of type Functor f =&gt; (a -&gt; b) -&gt; f a -&gt; f b
transforms the values in a computational context f using a pure function.
      </p>
      <p>In this definition the functorial constraint is required to apply the addition
function (+ offset) :: Value -&gt; Value to the instruction counter value
enclosed in a computational context f. We therefore say that jump has functorial
semantics, whereas load has unconstrained semantics, since the read and write
terms had no constraint.</p>
      <p>Later in the paper we will instantiate f with an appropriate context for data
dependency tracking. As it turns out, instructions that have unconstrained or
functorial semantics can have at most one read dependency: there is no way
to combine multiple read results. To do that, we need applicative semantics, as
demonstrated by the next example.</p>
      <p>Add The add instruction performs the addition of the values of a register and
a memory cell, writing the result back into the same register. If the result of
the addition is equal to zero, the instruction sets the Zero flag of the processor
to True, and to False otherwise.</p>
      <p>The semantics definition is a bit more involved than the previous ones,
because the Functor context is not expressive enough and a more powerful
abstraction is needed. The following definition of add requires f to be at least
an Applicative:
add reg addr = \read write -&gt; Just $
let result = (+) &lt;$&gt; read (Reg reg) &lt;*&gt; read (Addr addr)
isZero = (== 0) &lt;$&gt; result
in write (Reg reg) result *&gt;</p>
      <p>write (Flag Zero) (boolToValue &lt;$&gt; isZero)
Let us elaborate on what is going on here. The definition may be broken down
into three parts: reading data, processing it, and writing data back in the
processor state.</p>
      <p>The first let-binding uses Applicative notation to read the values from the
register reg and memory address addr and add them up. Note that this notation
is declarative, hence it rather states that the result is supposed to be a sum of
values of two entities than performs actual computation. This intuition is very
important for understanding the static dependency tracking of instructions: keys
Reg reg and Addr addr are declared as static input dependencies of the add
instruction. However, since the semantics may be executed in any Applicative
context, this dependency-tracking interpretation does not prevent other possible
interpretations of the very same definition of the semantics. For instance, in a
simulation context, the result will be computed based on concrete data values
read from the current processor state.</p>
      <p>The second line of the let-binding is quite similar to the expression in the
semantics of the jump instruction. The type of the result is f Value, hence the
zero testing function (== 0) of type Value -&gt; Bool must be mapped over the
context f with the operator &lt;$&gt; to obtain the value of type f Bool.</p>
      <p>
        The last two lines of the definition perform two write operations chained with
the applicative operator *&gt; of type Applicative f =&gt; f a -&gt; f b -&gt; f b.
This declares the keys Reg reg and Flag Zero to be output dependencies of
the computation and that the writes must be both performed. The the read and
write terms now have the following types:
read :: forall f. Applicative f =&gt; Key -&gt; f Value
write :: forall f. Applicative f =&gt; Key -&gt; f Value -&gt; f ()
An interesting feature of the Applicative notation is that it does not specify
the exact order of performing actions. This is useful in embedded domain-specific
languages with concurrency, for instance Facebook’s Haxl [
        <xref ref-type="bibr" rid="ref11">11</xref>
        ]. This insight can
also be used to extract concurrency from instruction descriptions.
      </p>
      <p>Applicative functors are powerful enough to express the semantics of a large
class of instructions. In this paper we exploit their features to not only specify
the execution semantics but also automatically track static data dependencies
of instructions. However not every instruction can be expressed with applicative
semantics. If the behaviour depends on the actual data values, i.e. when dynamic
data dependencies emerge, a more powerful monadic semantics is required.
Indirect load The indirect memory access instruction looks up a value in a
memory cell and uses it as the effective address in the regular load instruction.
Since the effective address can not be determined statically in the general case,
this instruction has a dynamic data dependency. The polymorphic
computational metalanguage requires the context f to be a Monad in order to be able to
encode such behaviour. Consider the definition of the semantics of the loadMI
instruction, which uses Haskell’s monadic do-notation:
loadMI reg addr read write = Just $ do
addr’ &lt;- read (Addr addr)
write (Reg reg) (read (Addr addr’))
The first line extracts the effective address from the monadic context f and binds
the identifier addr’ to it. Here is the catch: expressions on left-hand-side and
right-hand-side of the &lt;- symbol have different types. The read (Addr addr) is
of type Monad f =&gt; f Value and the identifier addr’ has type Value. The main
feature of Monad is the ability to extract a value from an effectful context and
pass it in the further computation as if it was pure. This gives us a possibility
to pass the addr’ as an argument to the next read operation.</p>
      <p>Monadic semantics is more powerful than unconstrained, functorial and
applicative ones, but we are no longer able to extract all the dependencies of the
computation if f is restricted to Monad, since some of them will not be static.
Therefore, concurrency oracles can not be built for Monad-flavoured
computations, or at least, they can no longer be exact and must be approximate (for
example, one might conservatively say that loadMI has a read dependency on
every possible memory address, but no register read dependencies).</p>
      <p>We have given examples of four types of semantic computations: unrestricted,
functorial, applicative and monadic. In every definition we used functions read
and write with appropriate constraints on the context f. To recap, here are the
four different types for the read function:
read :: forall f. Key -&gt; f Value
read :: forall f. Functor f =&gt; Key -&gt; f Value
read :: forall f. Applicative f =&gt; Key -&gt; f Value
read :: forall f. Monad f =&gt; Key -&gt; f Value
One can clearly see a pattern, and Haskell’s type system is powerful enough to
abstract over it. Generic read and write may be assigned the following types:
read :: forall f. c f =&gt; Key -&gt; f Value
write :: forall f. c f =&gt; Key -&gt; f Value -&gt; f ()
Here, the variable c must have the kind * -&gt; Constraint. This allows to
instantiate c with NoConstraint, Functor, Applicative, Monad or any other suitable
constraint, thus making the metalanguage polymorphic in the computational
context.</p>
      <p>The next section will present a formal definition of the metalanguage,
instruction and program semantics. The section 4 will describe the construction
of concurrency oracles for programs comprising unrestricted, functorial,
applicative, but not monadic instructions.
3</p>
    </sec>
    <sec id="sec-3">
      <title>Polymorphic computational metalanguage</title>
      <p>In the previous section we have described the semantics of several instructions
of a generic computer architecture in terms of a polymorphic computational
metalanguage. This section presents the formal definition of the metalanguage
and provides a more formal description of the instruction and program semantics.</p>
      <p>
        A remark on formal definitions Before we start, let us make a remark
on what we consider a formal definition. We do not aim to formalise our tools in
any kind of foundational mathematical system, such as ZF5 or homotopy type
theory. We are presenting an elegant way of solving a well-known problem and
we use the Haskell programming language to implement the solution. Therefore,
we consider a concept to be formally defined if it is expressed as a Haskell data
type. This may sound hand-wavy, but since Haskell has a static type system (a
variant of System F [
        <xref ref-type="bibr" rid="ref19">19</xref>
        ]) and operational semantics, we can be formal enough.
      </p>
      <p>Definition (polymorphic computational metalanguage): A term of
the metalanguage is a value of the following Haskell type:
type Semantics c a =
forall f. c f =&gt; (Key -&gt; f Value)
-&gt; (Key -&gt; f Value -&gt; f ())
-&gt; Maybe (f a)
5 Zermelo-Fraenkel set theory.
A Semantics is essentially a rank-2 polymorphic6 effectful computation
depending on two functions, which we will usually refer to as read and write.</p>
      <p>Let us now give some intuition for the components of the metalanguage.
The Semantics c a type may be thought as a mutable dictionary. The read
function has type Key -&gt; f Value — it takes a key and gives back an effectful
value looked up in the dictionary. The write function takes a key and an
effectful value and alters the value of the key in the dictionary. The semantics can be
partial, hence the the return type f a is wrapped in the Maybe type
constructor. Maybe7 is an idiomatic Haskell encoding of partial definitions. The
semantics may become partial if we, for example, fix the constraint type variable c
to Applicative, thus losing the possibility to encode the monadic components
of the instruction set. Maybe allows us to treat such partially-defined semantics
in a safe and formal way.</p>
      <sec id="sec-3-1">
        <title>Definition (Instruction Set): An instruction set is an algebraic data type</title>
        <p>with as many data constructors as there are instructions. If an instruction has
an argument, it is defined as an argument of the corresponding data constructor.</p>
        <p>Consider an example definition of an instruction set consisting of instructions
described in the previous sections and the related auxiliary types:
data Instruction = Load Register MemoryAddress
| LoadMI Register MemoryAddress
| Add Register MemoryAddress
| Jump Value
data Register = R0 | R1 | R2 | R3
type MemoryAddress = Value</p>
      </sec>
      <sec id="sec-3-2">
        <title>Definition (Instruction Set Semantics): The semantics of an instruction</title>
        <p>set is a Haskell function mapping data constructors of the instruction set to the
terms of the polymorphic computational metalanguage.</p>
        <p>The definition of an instruction set semantics is the point where the
metalanguage has to be made monomorphic, i.e. the context constraint has to be
instantiated with a concrete one. Below we present unrestricted, functorial,
applicative and monadic semantics for the defined instruction set.</p>
        <p>We start from the Load instruction which may be executed in any context8:
semanticsU :: Instruction -&gt; Semantics Unrestricted ()
semanticsU (Load reg addr) = load reg addr
semanticsU _ = const (const Nothing)
6 A rank-2 polymorphic function is one taking as a parameter another function, which
is in turn (rank-1) polymorphic. This feature requires the RankNTypes language
extension of the Glasgow Haskell Compiler.
7 Defined in the Haskell’s base library as data Maybe a = Just a | Nothing.
8 The Unrestricted constraint is not exactly idiomatic Haskell and requires some
tricks to be defined.</p>
        <p>Note that the Haskell wildcard pattern ‘_’ is used to match all instructions
that require a more restrictive context. The const (const Nothing) expression
is equivalent to \read write -&gt; Nothing and constructs a stub for these more
restricted semantics. The function load has been defined in §2.</p>
        <p>The instantiation of c with a Functor allows us to implement the semantics
of the instruction Jump:
semanticsF :: Instruction -&gt; Semantics Functor ()
semanticsF (Jump simm) = jump simm
semanticsF i = semanticU i
Here we use the definition of jump from §2 and fall back to unrestricted semantics
definition semanticU for the Load instruction, hence avoiding code duplication.</p>
        <p>The remaining definitions are analogous:
semanticsA :: Instruction -&gt; Semantics Applicative ()
semanticsA (Add reg addr) = add reg addr
semanticsA i = semanticsF i
semanticsM :: Instruction -&gt; Semantics Monad ()
semanticsM (LoadMI reg addr) = loadMI reg addr
semanticsM i = semanticsA i</p>
        <p>We can now define the semantics of a block of instructions by reducing a
given list of instructions:
blockSemanticsA :: [Instruction] -&gt; Semantics Applicative ()
blockSemanticsA xs = \r w -&gt;
foldr (\x acc -&gt; (*&gt;) &lt;$&gt; acc &lt;*&gt; semanticsA x r w) nop xs
where nop = Just $ pure ()
The semantics of an empty block is nop (i.e. a no-op instruction). The semantics
of a non-empty list is the semantics of its head chained with the semantics of
the tail. We need to lift the applicative chaining operation since the Maybe type
constructor also is an instance of Applicative and the behaviour of *&gt; returns
the contents of the last Just, which is would be wrong.</p>
        <p>Now, with the instruction semantics defined in terms of the polymorphic
computational metalanguage, we may proceed to evaluating the metalanguage
in concrete contexts to get a practical interpretation of the instruction set.</p>
        <p>The next section presents the interpretation of unrestricted, functorial and
applicative instructions yielding concurrency oracles for programs.</p>
        <p>
          Other interpretations of the metalanguage are also possible. In the technical
report [
          <xref ref-type="bibr" rid="ref16">16</xref>
          ] we present a formal model of a processor developed for space missions,
where we use a more restricted, monadic metalanguage, making emphasis on
symbolic program execution and automated theorem proving: the framework
allows to verify functional properties of programs and automatically check if
two programs are semantically equivalent. The metalanguage presented in this
paper also allows these interpretations, but the focus of this paper is different:
automated derivation of concurrency oracles.
        </p>
      </sec>
    </sec>
    <sec id="sec-4">
      <title>Concurrency oracles</title>
      <p>In this section we present a method to derive concurrency oracles from the
instruction semantics encoded in the metalanguage (Definition 3). More
specifically, we aim to reason about instructions that have only static dependencies.</p>
      <p>We start by introducing formal definitions and Haskell encodings of the
concepts required for building concurrency oracles. First, we define the notions of
input and output dependencies of a computation.</p>
      <p>Definition (input dependency): Consider a term f of an applicative
metalanguage Semantics Applicative a. A key k is an input dependency of the
term f if the term f performs a read of the key k.</p>
      <sec id="sec-4-1">
        <title>Definition (output dependency): Consider a term f of an applicative</title>
        <p>metalanguage Semantics Applicative a. A key k is an output dependency of
the term f if the term f performs a write of the key k.</p>
        <p>Definition (dependencies): Consider a term f of an applicative
metalanguage Semantics Applicative a. The dependencies of the term f are sets I
and O – the input and output dependencies of the term f , respectively.</p>
        <p>In the Haskell implementation, we do not distinguish between input and
output dependencies in the type level, thus the function determining the
dependencies of a computation has the following type:</p>
        <p>dependencies :: Semantics Applicative a -&gt; Maybe ([Key], [Key])
The Maybe type constructor comes from the definition of the metalanguage: if the
applicative semantics is partial (returns Nothing) it is impossible to extract its
static dependencies. Successful static analysis yields a pair of lists representing
the sets of input and output dependencies of a computation.</p>
        <p>To extract the static data dependencies of an applicative computation we
need to interpret its semantics in the special context of a constant functor.
4.1</p>
      </sec>
      <sec id="sec-4-2">
        <title>The constant functor</title>
        <p>
          The Const a b data type is defined as follows [
          <xref ref-type="bibr" rid="ref12">12</xref>
          ]:
        </p>
        <p>newtype Const a b = Const { getConst :: a }
A value of the Const a b is just a value of any type a wrapped in a data
constructor. However, it is important that the type constructor has a phantom
type variable. This type variable allows us to declare useful instances of standard
Haskell type classes such as Functor and Applicative for Const a. We would
like to use this data type as a computational context for applicative semantics,
hence we declare the corresponding instance9:
instance Monoid m =&gt; Applicative (Const m) where
pure _ = Const mempty</p>
        <p>Const x &lt;*&gt; Const y = Const (x ‘mappend‘ y)
9 Const a also has a Functor instance, where fmap _ (Const x) = Const x.</p>
        <p>This instance exactly describes the desired behaviour of static dependency
tracking computational context. Const [Key] is an applicative functor that
ignores its enclosed value, but accumulates the declared dependencies using
the Monoid instance for Haskell list data type10.
4.2</p>
      </sec>
      <sec id="sec-4-3">
        <title>Extracting dependencies</title>
        <p>Using the seemingly vacuous datatype Const we define the function dependencies:
dependencies :: Semantics Applicative a -&gt; Maybe ([Key], [Key])
dependencies s = partitionEithers . getConst &lt;$&gt; s read write
where read k = Const [Left k]</p>
        <p>write k fv = fv *&gt; Const [Right k]
We instantiate the polymorphic computation context with f = Const [Key]
and supply custom tracking read and write functions. In fact, read does not
perform any reading and just tracks the key as an input dependency, whereas
write tracks the key as an output dependency and executes the effectful
computation fv, to appropriately track its dependencies. The resulting list of keys
gets unwrapped and unzipped by standard partitionEithers . getConst.</p>
        <p>This whole paper is built around the above three-line implementation of the
function dependencies: the rest is just functional programming background and
folklore, which is required for understanding these three lines of code.</p>
        <p>Fully armed with static dependency analysis, we can now define concurrency
oracles for programs written in the presented metalanguage.
4.3</p>
      </sec>
      <sec id="sec-4-4">
        <title>Concurrency oracle</title>
        <p>A concurrency oracle is a function taking two computations and statically
determining if they are data concurrent, i.e. do not share any data dependencies.</p>
        <p>Definition (Concurrency Oracle Answer): Two terms of the
metalanguage are concurrent if they do not share any data dependencies. They are in
a read or write conflict if they share any input or output dependencies,
respectively. If the share both input and output dependencies then they are considered
to be in a read-write conflict. We use the following data type is used to encode
concurrency oracle answers:
data OracleAnswer k = Concurrent
| ReadConflict [k]
| WriteConflict [k]
| ReadWriteConflict [k]</p>
        <p>Definition (concurrency oracle): Consider two terms with applicative
semantics s1 and s2 of the type Semantics Applicative a. A concurrency
oracle is a function of the following type:
10 The empty list [] is the monoid identity element and the list concatenation (++) is
the associative binary operation.
concurrencyOracle :: Eq k =&gt; Semantics Applicative k v1 a
-&gt; Semantics Applicative k v2 a
-&gt; Maybe (OracleAnswer k)
The function is required to return Nothing when one of the given semantics is
undefined, e.g. if it corresponds to an instruction with dynamic dependencies.
Below is one possible implementation:
concurrencyOracle s1 s2 = do
(r1, w1) &lt;- dependencies s1
(r2, w2) &lt;- dependencies s2
let readConflicts = intersect r1 r2
writeConflicts = intersect w1 w2
readWriteConflicts = intersect (r1 ++ w1) (r2 ++ w2)
pure $ case (readConflicts, writeConflicts, readWriteConflicts) of
([], [], [] ) -&gt; Concurrent
(rs, [], rws) | rs == rws -&gt; ReadConflict rs
([], ws, rws) | ws == rws -&gt; WriteConflict ws
(_ , _ , rws) -&gt; ReadWriteConflict rws</p>
        <p>The oracle determines static dependencies of two given terms and examines
several possible cases of the intersections of their input and output dependencies.</p>
      </sec>
      <sec id="sec-4-5">
        <title>4.4 Example oracles</title>
        <p>In this subsection we show two examples to illustrate the usage of concurrency
oracles. The examples are given in the form of interactive sessions, where ‘ghci&gt;’
denotes the command prompt.</p>
        <p>Two Load instructions with different arguments are concurrent as confirmed
by the oracle returning the result Just Concurrent:
ghci&gt; concurrencyOracle (semanticsA (Load R0 0))</p>
        <p>(semanticsA (Load R1 1))</p>
        <p>Just Concurrent
Extending the first computation with an additional Add instruction causes a read
conflict, as desired:
ghci&gt; p1 = blockSemanticsA [Load R0 0, Add R0 1]
ghci&gt; p2 = semanticsA (Load R1 1)
ghci&gt; concurrencyOracle p1 p2</p>
        <p>Just (ReadConflict [Addr 1])
We can overlay dependency graphs of programs p1 and p2 as follows (we place
the programs at starting addresses 10 and 20, respectively):
ghci&gt; Just g1 = programDataGraph (zip [10..] [Load R0 0, Add R0 1])
ghci&gt; Just g2 = programDataGraph (zip [20..] [Load R1 1])
ghci&gt; drawGraph (overlay g1 g2)
The resulting dependency graph is shown in Fig. 2. As one can see, the programs
have a read conflict on key Addr 1, just like the oracle has determined.</p>
      </sec>
    </sec>
    <sec id="sec-5">
      <title>Synthesis of efficient hardware microcontrollers</title>
      <p>
        In this section we present a method for extracting behavioural scenarios from
system control programs and synthesising hardware microcontrollers that can
execute these scenarios. We rely on Conditional Partial Order Graphs (CPOGs) [
        <xref ref-type="bibr" rid="ref13">13</xref>
        ]
and associated tool support for synthesis; specifically, we use the CPOG
plugin [
        <xref ref-type="bibr" rid="ref1">1</xref>
        ] of the Workcraft framework [
        <xref ref-type="bibr" rid="ref2">2</xref>
        ], which provides support for scenario
specification and synthesis, and handles the translation of CPOGs to circuits to
produce a physical implementation of the system microcontroller.
5.1
      </p>
      <sec id="sec-5-1">
        <title>Extracting scenarios from programs</title>
        <p>
          We define a scenario as a partial order (PO) (I, ≺), i.e. a binary precedence
relation ≺ defined on a set of instructions I that satisfies two properties [
          <xref ref-type="bibr" rid="ref6">6</xref>
          ]:
– Irreflexivity: ∀a ∈ I, ¬(a ≺ a)
– Transitivity: ∀a, b, c ∈ I, (a ≺ b) ∧ (b ≺ c) ⇒ (a ≺ c)
        </p>
        <p>To extract scenarios from programs, we reuse the dependency analysis that
we developed for implementing concurrency oracles in the previous section. As
one can see from our definition of scenarios, we only require to keep the
information about the (partial) ordering of instructions. We can therefore discard the
unnecessary details about which particular register, flag or memory location was
the cause of the dependency, leading to the following procedure.</p>
      </sec>
      <sec id="sec-5-2">
        <title>Extracting the behavioural scenario from a program:</title>
        <p>1. Calculate all static data dependencies between the program instructions.
2. Construct the static dependency graph.
3. Contract data vertices, keeping the induced arcs between the instructions.
4. Perform the transitive closure of the resulting graph.
5.2</p>
      </sec>
      <sec id="sec-5-3">
        <title>Scenario encoding and synthesis</title>
        <p>In the context of this paper, we consider control systems which are programmed
in low-level assembly-like languages. Using the procedure from the previous
subsection, we can extract behavioural scenarios, represented as partial orders, from
the system’s control programs. These partial orders often have some shared
functionality, which can be exploited by Conditional Partial Order Graphs and
associated synthesis methods, leading to more efficient hardware implementations
compared to those obtained by implementing each scenario separately.</p>
      </sec>
      <sec id="sec-5-4">
        <title>Microcontroller synthesis:</title>
        <p>1. Extract the scenarios from a given set of system control programs.
2. Synthesise a CPOG containing all the scenarios.
3. Apply the CPOG workflow for optimisation and compilation to hardware.</p>
        <p>In the next subsection we will illustrate the described microcontroller
synthesis approach on a simple example. We will consider a system with two control
programs, extract the scenarios from these programs and synthesise them into
a CPOG with some shared functionality.
5.3</p>
      </sec>
      <sec id="sec-5-5">
        <title>Example</title>
        <p>To illustrate the use of the scenario extraction procedure, let us sketch an
example of a system controlling a hypothetical dual-motor autonomous vehicle.
The vehicle has two motors directly driving its left and right front wheels. The
system control unit has a simple application-specific instruction set, two
generalpurpose registers and a memory unit with four cells. The input to the unit is
provided in memory cells 0 and 1. The unit controls the velocity of the left and
right motors by outputting values to the cells 2 and 3, respectively. A motor’s
velocity may be adjusted with the instruction Adjust supplying the input value
in a register and referring a target motor (2 or 3).</p>
        <p>The first program (Fig. 3, left) implements the “drive straight” behaviour,
driving both wheels with the same velocity. The graph on the right pictures the
extracted partial order.
1
2
3</p>
        <p>Load R0 0
Adjust R0 2</p>
        <p>Adjust R0 3</p>
        <p>Another behaviour is “drive and turn”, which is implemented by adjusting
the velocities with different values (Fig. 4). In this case, the resulting partial
order contains two independent components.</p>
        <p>Fig. 5 displays the Conditional Partial Order Graph which represents the
composition of the two scenarios, where the additional control input x 0 is used
to select the active scenario. The partial orders extracted from the programs are
efficiently merged, thus rendering the CPOG composition to be more compact
then a simple list of the extracted scenarios. The resulting hardware
microcontroller, mapped to a 2-input gate library, is shown in Fig. 6.</p>
      </sec>
    </sec>
    <sec id="sec-6">
      <title>Conclusion</title>
      <p>The paper presented a metalanguage for describing the semantics of instruction
set architectures. Multiple interpretations of the metalanguage terms allow us
to evaluate the semantics in different contexts without its modification. As the
primary application, we present an approach to deriving concurrency oracles of
the instructions with only static data dependencies.</p>
      <p>
        To handle instructions whose dependencies are dynamic, it is possible to
use conservative approximation of dependencies. For example, Fig. 7 shows the
dependency graph for a program implementing the Euclidean algorithm for
computing the greatest common divisor of two numbers that contains a conditional
branch instruction JumpZero, which modifies the instruction counter IC only
if the previous instruction set the Zero flag. In this example, we conservatively
assume that JumpZero always depends on IC. Our future work includes the
application of the presented methodology to extracting concurrency from real-world
processor specifications, as described in [
        <xref ref-type="bibr" rid="ref16">16</xref>
        ].
      </p>
      <p>0 Set R0 0</p>
    </sec>
  </body>
  <back>
    <ref-list>
      <ref id="ref1">
        <mixed-citation>
          1.
          <article-title>Scenco plugin repository, GitHub repository: github</article-title>
          .com/tuura/scenco
        </mixed-citation>
      </ref>
      <ref id="ref2">
        <mixed-citation>2. Workcraft, GitHub repository: github.com/workcraft/workcraft, Workcraft website: www.workcraft.org</mixed-citation>
      </ref>
      <ref id="ref3">
        <mixed-citation>
          3.
          <string-name>
            <surname>Van der Aalst</surname>
          </string-name>
          , W.: Process Mining: Discovery, Conformance and Enhancement of Business Processes. Springer (
          <year>2011</year>
          )
        </mixed-citation>
      </ref>
      <ref id="ref4">
        <mixed-citation>
          4.
          <string-name>
            <surname>Van der Aalst</surname>
          </string-name>
          , W.,
          <string-name>
            <surname>Weijters</surname>
            ,
            <given-names>T.</given-names>
          </string-name>
          ,
          <string-name>
            <surname>Maruster</surname>
            ,
            <given-names>L.</given-names>
          </string-name>
          :
          <article-title>Workflow mining: Discovering process models from event logs</article-title>
          .
          <source>IEEE Transactions on Knowledge and Data Engineering</source>
          <volume>16</volume>
          (
          <issue>9</issue>
          ),
          <fpage>1128</fpage>
          -
          <lpage>1142</lpage>
          (
          <year>2004</year>
          )
        </mixed-citation>
      </ref>
      <ref id="ref5">
        <mixed-citation>
          5.
          <string-name>
            <surname>Augusto</surname>
            ,
            <given-names>A.</given-names>
          </string-name>
          ,
          <string-name>
            <surname>Conforti</surname>
            ,
            <given-names>R.</given-names>
          </string-name>
          ,
          <string-name>
            <surname>Dumas</surname>
            ,
            <given-names>M.</given-names>
          </string-name>
          ,
          <string-name>
            <given-names>La</given-names>
            <surname>Rosa</surname>
          </string-name>
          ,
          <string-name>
            <given-names>M.</given-names>
            ,
            <surname>Maggi</surname>
          </string-name>
          ,
          <string-name>
            <given-names>F.M.</given-names>
            ,
            <surname>Marrella</surname>
          </string-name>
          ,
          <string-name>
            <given-names>A.</given-names>
            ,
            <surname>Mecella</surname>
          </string-name>
          ,
          <string-name>
            <given-names>M.</given-names>
            ,
            <surname>Soo</surname>
          </string-name>
          ,
          <string-name>
            <surname>A.</surname>
          </string-name>
          :
          <article-title>Automated discovery of process models from event logs: Review and benchmark</article-title>
          .
          <source>arXiv preprint arXiv:1705.02288</source>
          (
          <year>2017</year>
          )
        </mixed-citation>
      </ref>
      <ref id="ref6">
        <mixed-citation>
          6.
          <string-name>
            <surname>Birkhoff</surname>
          </string-name>
          , G.:
          <article-title>Lattice Theory</article-title>
          . No. v.
          <volume>25</volume>
          , pt. 2 in American Mathematical Society colloquium publications,
          <source>American Mathematical Society</source>
          (
          <year>1940</year>
          ), https://books. google.co.uk/books?id=0Y8d-MdtVwkC
        </mixed-citation>
      </ref>
      <ref id="ref7">
        <mixed-citation>
          7.
          <string-name>
            <surname>Cook</surname>
            ,
            <given-names>J.E.</given-names>
          </string-name>
          ,
          <string-name>
            <surname>Wolf</surname>
            ,
            <given-names>A.L.</given-names>
          </string-name>
          :
          <article-title>Event-based detection of concurrency</article-title>
          .
          <source>In: ACM SIGSOFT Software Engineering Notes</source>
          . vol.
          <volume>23</volume>
          , pp.
          <fpage>35</fpage>
          -
          <lpage>45</lpage>
          . ACM (
          <year>1998</year>
          )
        </mixed-citation>
      </ref>
      <ref id="ref8">
        <mixed-citation>
          8.
          <string-name>
            <surname>Dumas</surname>
            ,
            <given-names>M.</given-names>
          </string-name>
          ,
          <string-name>
            <surname>Garc´</surname>
          </string-name>
          ıa-Ban˜uelos, L.:
          <article-title>Process mining reloaded: Event structures as a unified representation of process models and event logs</article-title>
          .
          <source>In: International Conference on Applications and Theory of Petri Nets and Concurrency</source>
          . pp.
          <fpage>33</fpage>
          -
          <lpage>48</lpage>
          . Springer (
          <year>2015</year>
          )
        </mixed-citation>
      </ref>
      <ref id="ref9">
        <mixed-citation>
          9.
          <string-name>
            <surname>Fox</surname>
            ,
            <given-names>A.</given-names>
          </string-name>
          ,
          <string-name>
            <surname>Myreen</surname>
            ,
            <given-names>M.O.:</given-names>
          </string-name>
          <article-title>A trustworthy monadic formalization of the ARMv7 instruction set architecture</article-title>
          .
          <source>In: International Conference on Interactive Theorem Proving</source>
          . pp.
          <fpage>243</fpage>
          -
          <lpage>258</lpage>
          . Springer (
          <year>2010</year>
          )
        </mixed-citation>
      </ref>
      <ref id="ref10">
        <mixed-citation>
          10.
          <string-name>
            <surname>Kennedy</surname>
            ,
            <given-names>A.</given-names>
          </string-name>
          ,
          <string-name>
            <surname>Benton</surname>
            ,
            <given-names>N.</given-names>
          </string-name>
          ,
          <string-name>
            <surname>Jensen</surname>
            ,
            <given-names>J.B.</given-names>
          </string-name>
          ,
          <string-name>
            <surname>Dagand</surname>
            ,
            <given-names>P.E.</given-names>
          </string-name>
          :
          <article-title>Coq: the world's best macro assembler?</article-title>
          <source>In: Proceedings of the 15th Symposium on Principles and Practice of Declarative Programming</source>
          . pp.
          <fpage>13</fpage>
          -
          <lpage>24</lpage>
          . ACM (
          <year>2013</year>
          )
        </mixed-citation>
      </ref>
      <ref id="ref11">
        <mixed-citation>
          11.
          <string-name>
            <surname>Marlow</surname>
            ,
            <given-names>S.</given-names>
          </string-name>
          ,
          <string-name>
            <surname>Brandy</surname>
            ,
            <given-names>L.</given-names>
          </string-name>
          ,
          <string-name>
            <surname>Coens</surname>
            ,
            <given-names>J.</given-names>
          </string-name>
          ,
          <string-name>
            <surname>Purdy</surname>
          </string-name>
          , J.:
          <article-title>There is No Fork: An Abstraction for Efficient, Concurrent, and Concise Data Access</article-title>
          .
          <source>SIGPLAN Not</source>
          .
          <volume>49</volume>
          (
          <issue>9</issue>
          ),
          <fpage>325</fpage>
          -
          <lpage>337</lpage>
          (
          <year>Aug 2014</year>
          )
        </mixed-citation>
      </ref>
      <ref id="ref12">
        <mixed-citation>
          12.
          <string-name>
            <surname>McBride</surname>
            ,
            <given-names>C.</given-names>
          </string-name>
          ,
          <string-name>
            <surname>Paterson</surname>
          </string-name>
          , R.:
          <article-title>Applicative programming with effects</article-title>
          .
          <source>J. Funct. Program</source>
          .
          <volume>18</volume>
          (
          <issue>1</issue>
          ),
          <fpage>1</fpage>
          -
          <lpage>13</lpage>
          (
          <year>Jan 2008</year>
          )
        </mixed-citation>
      </ref>
      <ref id="ref13">
        <mixed-citation>
          13.
          <string-name>
            <surname>Mokhov</surname>
            ,
            <given-names>A.</given-names>
          </string-name>
          :
          <article-title>Conditional Partial Order Graphs</article-title>
          .
          <source>Ph.D. thesis</source>
          , Newcastle University (
          <year>2009</year>
          )
        </mixed-citation>
      </ref>
      <ref id="ref14">
        <mixed-citation>
          14.
          <string-name>
            <surname>Mokhov</surname>
            ,
            <given-names>A.</given-names>
          </string-name>
          :
          <article-title>Algebraic Graphs with Class (Functional Pearl)</article-title>
          .
          <source>In: Proceedings of the International Symposium on Haskell. ACM</source>
          (
          <year>2017</year>
          )
        </mixed-citation>
      </ref>
      <ref id="ref15">
        <mixed-citation>
          15.
          <string-name>
            <surname>Mokhov</surname>
            ,
            <given-names>A.</given-names>
          </string-name>
          ,
          <string-name>
            <surname>Carmona</surname>
            ,
            <given-names>J.</given-names>
          </string-name>
          ,
          <string-name>
            <surname>Beaumont</surname>
          </string-name>
          , J.:
          <article-title>Mining conditional partial order graphs from event logs</article-title>
          .
          <source>In: Transactions on Petri Nets and Other Models of Concurrency XI</source>
          , pp.
          <fpage>114</fpage>
          -
          <lpage>136</lpage>
          . Springer (
          <year>2016</year>
          )
        </mixed-citation>
      </ref>
      <ref id="ref16">
        <mixed-citation>
          16.
          <string-name>
            <surname>Mokhov</surname>
            ,
            <given-names>A.</given-names>
          </string-name>
          ,
          <string-name>
            <surname>Lukyanov</surname>
            ,
            <given-names>G.</given-names>
          </string-name>
          ,
          <string-name>
            <surname>Lechner</surname>
          </string-name>
          , J.:
          <article-title>Formal verification of spacecraft control programs using a metalanguage for state transformers</article-title>
          . arXiv preprint arXiv:
          <year>1802</year>
          .
          <volume>01738</volume>
          (
          <year>2018</year>
          )
        </mixed-citation>
      </ref>
      <ref id="ref17">
        <mixed-citation>
          17.
          <string-name>
            <given-names>Peyton</given-names>
            <surname>Jones</surname>
          </string-name>
          ,
          <string-name>
            <given-names>S.</given-names>
            ,
            <surname>Vytiniotis</surname>
          </string-name>
          ,
          <string-name>
            <given-names>D.</given-names>
            ,
            <surname>Weirich</surname>
          </string-name>
          ,
          <string-name>
            <given-names>S.</given-names>
            ,
            <surname>Shields</surname>
          </string-name>
          ,
          <string-name>
            <surname>M.</surname>
          </string-name>
          :
          <article-title>Practical type inference for arbitrary-rank types</article-title>
          .
          <source>Journal of functional programming 17(1)</source>
          ,
          <fpage>1</fpage>
          -
          <lpage>82</lpage>
          (
          <year>2007</year>
          )
        </mixed-citation>
      </ref>
      <ref id="ref18">
        <mixed-citation>
          18.
          <string-name>
            <surname>Research</surname>
            ,
            <given-names>A.L.</given-names>
          </string-name>
          :
          <string-name>
            <surname>Graphviz - Graph Visualization Software</surname>
          </string-name>
          (
          <year>1991</year>
          ), https://www. graphviz.org/
        </mixed-citation>
      </ref>
      <ref id="ref19">
        <mixed-citation>
          19.
          <string-name>
            <surname>Sulzmann</surname>
            ,
            <given-names>M.</given-names>
          </string-name>
          ,
          <string-name>
            <surname>Chakravarty</surname>
            ,
            <given-names>M.M.T.</given-names>
          </string-name>
          ,
          <string-name>
            <surname>Jones</surname>
            ,
            <given-names>S.P.</given-names>
          </string-name>
          ,
          <string-name>
            <surname>Donnelly</surname>
            ,
            <given-names>K.</given-names>
          </string-name>
          :
          <article-title>System f with type equality coercions</article-title>
          .
          <source>In: Proceedings of the 2007 ACM SIGPLAN International Workshop on Types in Languages Design and Implementation</source>
          . pp.
          <fpage>53</fpage>
          -
          <lpage>66</lpage>
          . TLDI '07,
          <string-name>
            <surname>ACM</surname>
          </string-name>
          (
          <year>2007</year>
          )
        </mixed-citation>
      </ref>
    </ref-list>
  </back>
</article>