doc: refactor
authorSebastien Bourdeauducq <sebastien@milkymist.org>
Wed, 25 Jan 2012 19:01:45 +0000 (20:01 +0100)
committerSebastien Bourdeauducq <sebastien@milkymist.org>
Wed, 25 Jan 2012 19:01:45 +0000 (20:01 +0100)
README
doc/migen.txt [new file with mode: 0644]
doc/migen_logo.svg [new file with mode: 0644]

diff --git a/README b/README
index 6970ba5391aa2cd4069eb22c0fa65a6bd4736fb2..660e217998ee841c9d72815748410218d369a0c6 100644 (file)
--- a/README
+++ b/README
-             Migen (Milkymist Generator)
-a Python toolbox for building complex digital hardware
-======================================================
+Migen (Milkymist Generator)
+  a Python toolbox for building complex digital hardware
 
-Background
-==========
-Even though the Milkymist system-on-chip [1] is technically successful,
-it suffers from several limitations stemming from its implementation in
-manually written Verilog HDL:
+Migen aims at automating further the VLSI design process. It provides
+tools to build synchronous designs more productively, integrate
+system-on-chips, design dataflow systems, and more. Migen will become
+the foundation for the next-generation Milkymist SoC.
 
-(1) The "event-driven" paradigm of today's dominant hardware descriptions
-languages (Verilog and VHDL, collectively referred to as "V*HDL" in the
-rest of this document) is often too general. Today's FPGA architectures
-are optimized for the implementation of fully synchronous circuits. This
-means that the bulk of the code for an efficient FPGA design falls into
-three categories:
-  (a) Combinatorial statements
-  (b) Synchronous statements
-  (c) Initialization of registers at reset
-V*HDL do not follow this organization. This means that a lot of
-repetitive manual coding is needed, which brings sources of human errors,
-petty issues, and confusion for beginners:
-  - wire vs. reg in Verilog
-  - forgetting to initialize a register at reset
-  - deciding whether a combinatorial statement must go into a
-    process/always block or not
-  - simulation mismatches with combinatorial processes/always blocks
-  - and more...
-A little-known fact about FPGAs is that many of them have to ability to
-initialize their registers from the bitstream contents. This can be done
-in a portable and standard way using an "initial" block in Verilog, and
-by affecting a value at the signal declaration in VHDL. This renders an
-explicit reset signal unnecessary in practice in some cases, which opens
-the way for further design optimization. However, this form of
-initialization is entirely not synthesizable for ASIC targets, and it is
-not easy to switch between the two forms of reset using V*HDL.
+See doc/migen.txt for a more complete description.
 
-(2) V*HDL support for composite types is very limited. Signals having a
-record type in VHDL are unidirectional, which makes them clumsy to use
-e.g. in bus interfaces. There is no record type support in Verilog, which
-means that a lot of copy-and-paste has to be done when forwarding grouped
-signals.
-
-(3) V*HDL support for procedurally generated logic is extremely limited.
-The most advanced forms of procedural generation of synthesizable logic
-that V*HDL offers are CPP-style directives in Verilog, combinatorial
-functions, and generate statements. Nothing really fancy, and it shows.
-To give a few examples:
-  - Building highly flexible bus interconnect is not possible. Even
-arbitrating any given number of bus masters for commonplace protocols
-such as Wishbone cannot be done with the tools at V*HDL puts at our
-disposal. This requires manual recoding of parts of the arbiter to add or
-remove a master, which is tedious and often cause frustrating errors.
-Each occurence of the latter can easily cause one or two hours of lost
-productivity when combined with the long compilation times of moderately
-complex system-on-chip designs.
-  - Building a memory infrastructure (including bus interconnect, bridges
-and caches) that can automatically adapt itself at compile-time to any
-word size of the SDRAM is clumsy and tedious.
-  - Building register banks for control, status and interrupt management
-of cores can also largely benefit from automation.
-  - Many hardware acceleration problems can fit into the dataflow
-programming model. Manual dataflow implementation in V*HDL has, again, a
-lot of redundancy and potential for human errors. See the Milkymist
-texture mapping unit [3][4] for an example of this. The amount of detail
-to deal with manually also makes the design space exploration difficult,
-and therefore hinders the design of efficient architectures.
-  - Pre-computation of values, such as filter coefficients for DSP or
-even simply trigonometric tables, must often be done using external tools
-whose results are copy-and-pasted (in the best cases, automatically) into
-the V*HDL source.
-
-Enter Migen, a Python toolbox for building complex digital hardware. We
-could have designed a brand new programming language, but that would have
-been reinventing the wheel instead of being able to benefit from Python's
-rich features and immense library. The price to pay is a slightly
-cluttered syntax at times when writing descriptions in FHDL, but we
-believe this is totally acceptable, particularly when compared to VHDL
-;-)
-
-Migen is made up of several related components, which are briefly
-described below.
-
-Migen FHDL
-==========
-The Fragmented Hardware Description Language (FHDL) is the lowest layer
-of Migen. It consists of a formal system to describe signals, and
-combinatorial and synchronous statements operating on them. The formal
-system itself is low level and close to the synthesizable subset of
-Verilog, and we then rely on Python algorithms to build complex
-structures by combining FHDL elements and encapsulating them in
-"fragments".
-The FHDL module also contains a back-end to produce synthesizable
-Verilog, and some basic analysis functions. It would be possible to
-develop a VHDL back-end as well, though more difficult than for Verilog -
-we are "cheating" a bit now as Verilog provides most of the FHDL
-semantics.
-
-FHDL differs from MyHDL [2] in fundamental ways. MyHDL follows the
-event-driven paradigm of traditional HDLs (see Background, #1) while FHDL
-separates the code into combinatorial statements, synchronous statements,
-and reset values. In MyHDL, the logic is described directly in the Python
-AST. The converter to Verilog or VHDL then examines the Python AST and
-recognizes a subset of Python that it translates into V*HDL statements.
-This seriously impedes the capability of MyHDL to generate logic
-procedurally. With FHDL, you manipulate a custom AST from Python, and you
-can more easily design algorithms that operate on it.
-
-FHDL is made of several elements, which are briefly explained below.
-
-BV
---
-The bit vector (BV) object defines if a constant or signal is signed or
-unsigned, and how many bits it has. This is useful e.g. to:
- - determine when to perform sign extension (FHDL uses the same rules as
-Verilog).
- - determine the size of registers.
- - determine how many bits should be used by each value in
-concatenations.
-
-Constant
---------
-This object should be self-explanatory. All constant objects contain a BV
-object and a value. If no BV object is specified, one will be made up
-using the following rules:
-  - If the value is positive, the BV is unsigned and has the minimum
-number of bits needed to represent the constant's value in the canonical
-base-2 system.
-  - If the value is negative, the BV is signed, and has the minimum
-number of bits needed to represent the constant's value in the canonical
-two's complement, base-2 system.
-
-Signal
-------
-The signal object represents a value that is expected to change in the
-circuit. It does exactly what Verilog's "wire" and "reg" and VHDL's
-"signal" and "variable" do.
-
-The main point of the signal object is that it is identified by its
-Python ID (as returned by the id() function), and nothing else. It is the
-responsibility of the V*HDL back-end to establish an injective mapping
-between Python IDs and the V*HDL namespace. It should perform name
-mangling to ensure this. The consequence of this is that signal objects
-can safely become members of arbitrary Python classes, or be passed as
-parameters to functions or methods that generate logic involving them.
-
-The properties of a signal object are:
-  - a bit vector description
-  - a name, used as a hint for the V*HDL back-end name mangler.
-  - a boolean "variable". If true, the signal will behave like a VHDL
-variable, or a Verilog reg that uses blocking assignment. This parameter
-only has an effect when the signal's value is modified in a synchronous
-statement.
-  - the signal's reset value. It must be an integer, and defaults to 0.
-When the signal's value is modified with a synchronous statement, the
-reset value is the initialization value of the associated register.
-When the signal is assigned to in a conditional combinatorial statement
-(If or Case), the reset value is the value that the signal has when no
-condition that causes the signal to be driven is verified. This enforces
-the absence of latches in designs. If the signal is permanently driven
-using a combinatorial statement, the reset value has no effect.
-  
-The sole purpose of the name property is to make the generated V*HDL code
-easier to understand and debug. From a purely functional point of view,
-it is perfectly OK to have several signals with the same name property.
-The back-end will generate a unique name for each object. If no name
-property is specified, Migen will analyze the code that created the
-signal object, and try to extract the variable or member name from there.
-It then uses the module name that created the signal, a underscore, and
-the variable name. For example, if we are in module "foo", the following
-statements will create one or several signal(s) named "foo_bar":
-  bar = Signal()
-  self.bar = Signal()
-  self.baz.bar = Signal()
-  bar = [Signal() for x in range(42)]
-
-Operators
----------
-Operators are represented by the _Operator object, which generally should
-not be used directly. Instead, most FHDL objects overload the usual
-Python logic and arithmetic operators, which allows a much lighter syntax
-to be used. For example, the expression:
-  a * b + c
-is equivalent to:
-  _Operator('+', [_Operator('*', [a, b]), c])
-  
-Slices
-------
-Likewise, slices are represented by the _Slice object, which often should
-not be used in favor of the Python slice operation [x:y].
-Implicit indices using the forms [x], [x:] and [:y] are supported.
-Beware! Slices work like Python slices, not like VHDL or Verilog slices.
-The first bound is the index of the LSB and is inclusive. The second
-bound is the index of MSB and is exclusive. In V*HDL, bounds are MSB:LSB
-and both are inclusive.
-
-Concatenations
---------------
-Concatenations are done using the Cat object. To make the syntax lighter,
-its constructor takes a variable number of arguments, which are the
-signals to be concatenated together (you can use the Python '*' operator
-to pass a list instead).
-To be consistent with slices, the first signal is connected to the bits
-with the lowest indices in the result. This is the opposite of the way
-the '{}' construct works in Verilog.
-
-Replications
-------------
-The Replicate object represents the equivalent of {count{expression}} in
-Verilog.
-
-Assignments
------------
-Assignments are represented with the _Assign object. Since using it
-directly would result in a cluttered syntax, the preferred technique for
-assignments is to use the eq() method provided by objects that can have a
-value assigned to them. They are signals, and their combinations with the
-slice and concatenation operators.
-As an example, the statement:
-  a[0].eq(b)
-is equivalent to:
-  _Assign(_Slice(a, 0, 1), b)
-
-If statement
-------------
-The If object takes a first parameter which must be an expression
-(combination of the Constant, Signal, _Operator, _Slice, etc. objects)
-representing the condition, then a variable number of parameters
-representing the statements (_Assign, If, Case, etc. objects) to be
-executed when the condition is verified.
-
-The If object defines a Else() method, which when called defines the
-statements to be executed when the condition is not true. Those
-statements are passed as parameters to the variadic method.
-
-For convenience, there is also a Elif() method.
-
-Example:
-If(tx_count16 == 0,
-    tx_bitcount.eq(tx_bitcount + 1),
-    If(tx_bitcount == 8,
-        self.tx.eq(1)
-    ).Elif(tx_bitcount == 9,
-        self.tx.eq(1),
-        tx_busy.eq(0)
-    ).Else(
-        self.tx.eq(tx_reg[0]),
-        tx_reg.eq(Cat(tx_reg[1:], 0))
-    )
-)
-
-Case statement
---------------
-The Case object constructor takes as first parameter the expression to be
-tested, then a variable number of lists describing the various cases.
-
-Each list contains an expression (typically a constant) describing the
-value to be matched, followed by the statements to be executed when there
-is a match. The head of the list can be the an instance of the Default
-object.
-
-Instances
----------
-Instance objects represent the parametrized instantiation of a V*HDL
-module, and the connection of its ports to FHDL signals. They are useful
-in a number of cases:
-  - reusing legacy or third-party V*HDL code.
-  - using special FPGA features (DCM, ICAP, ...).
-  - implementing logic that cannot be expressed with FHDL (asynchronous
-    circuits, ...).
-  - breaking down a Migen system into multiple sub-systems, possibly
-    using different clock domains.
-
-The properties of the instance object are:
-  - the type of the instance (i.e. name of the instantiated module).
-  - a list of output ports of the instantiated module. Each element of
-    the list is a pair containing a string, which is the name of the
-    module's port, and either an existing signal (on which the port will
-    be connected to) or a BV (which will cause the creation of a new
-    signal).
-  - a list of input ports (likewise).
-  - a list of (name, value) pairs for the parameters ("generics" in VHDL)
-    of the module.
-  - the name of the clock port of the module (if any). If this is
-    specified, the port will be connected to the system clock.
-  - the name of the reset port of the module (likewise).
-  - the name of the instance (can be mangled like signal names).
-
-Memories
---------
-Memories (on-chip SRAM) are not supported, but will be soon, using a
-mechanism similar to instances. (TODO)
-
-Fragments
----------
-A "fragment" is a unit of logic, which is composed of:
-  - a list of combinatorial statements.
-  - a list of synchronous statements.
-  - a list of instances.
-  - a list of memories.
-  - a set of pads, which are signals intended to be connected to
-    off-chip devices.
-
-Fragments can reference arbitrary signals, including signals that are
-referenced in other fragments. Fragments can be combined using the "+"
-operator, which returns a new fragment containing the concatenation of
-each pair of lists.
-
-Fragments can be passed to the back-end for conversion to Verilog.
-
-By convention, classes that generate logic implement a method called
-"get_fragment". When called, this method builds a new fragment
-implementing the desired functionality of the class, and returns it. This
-convention allows fragments to be built automatically by combining the
-fragments from all relevant objects in the local scope, by using the
-autofragment module.
-
-Migen Core Logic
-================
-Migen Core Logic is a convenience library of common logic circuits
-implemented using FHDL:
-  - a multi-cycle integer divider.
-  - a round-robin arbiter, useful to build bus arbiters.
-  - a multiplexer bank (multimux), useful to multiplex composite
-    (grouped) signals.
-  - a condition-triggered static scheduler of FHDL synchronous statements
-    (timeline).
-
-Migen Bus
-=========
-Migen Bus contains classes providing a common structure for master and
-slave interfaces of the following buses:
-  - Wishbone [5], the general purpose bus recommended by Opencores.
-  - CSR-NG, a low-bandwidth, resource-sensitive bus designed for
-    accessing the configuration and status registers of cores from
-    software.
-  - FastMemoryLink-NG, a split-transaction bus optimized for use with a
-    high-performance, out-of-order SDRAM controller. (TODO)
-
-It also provides interconnect components for these buses, such as
-arbiters and address decoders. The strength of the Migen procedurally
-generated logic can be illustrated by the following example:
-  wbcon = wishbone.InterconnectShared(
-      [cpu.ibus, cpu.dbus, ethernet.dma, audio.dma],
-      [(0, norflash.bus), (1, wishbone2fml.wishbone),
-      (3, wishbone2csr.wishbone)])
-In this example, the interconnect component generates a 4-way round-robin
-arbiter, multiplexes the master bus signals into a shared bus, determines
-that the address decoding must occur on 2 bits, and connects all slave
-interfaces to the shared bus, inserting the address decoder logic in the
-bus cycle qualification signals and multiplexing the data return path. It
-can recognize the signals in each core's bus interface thanks to the
-common structure mandated by Migen Bus. All this happens automatically,
-using only that much user code. The resulting interconnect logic can be
-retrieved using wbcon.get_fragment(), and combined with the fragments
-from the rest of the system.
-
-Migen Bank
-==========
-Migen Bank is a system comparable to wishbone-gen [6], which automates
-the creation of configuration and status register banks and
-(TODO) interrupt/event managers implemented in cores.
-
-Bank takes a description made up of a list of registers and generates
-logic implementing it with a slave interface compatible with Migen Bus.
-
-A register can be "raw", which means that the core has direct access to
-it. It also means that the register width must be less or equal to the
-bus word width. In that case, the register object provides the following
-signals:
-  - dev_r, which contains the data written from the bus interface.
-  - dev_re, which is the strobe signal for dev_r. It is active for one
-    cycle, after or during a write from the bus. dev_r is only valid when
-    dev_re is high.
-  - dev_w, which must provide at all times the value to be read from the
-    bus.
-
-Registers that are not raw are managed by Bank and contain fields. If the
-sum of the widths of all fields attached to a register exceeds the bus
-word width, the register will automatically be sliced into words of the
-maximum size and implemented at consecutive bus addresses, MSB first.
-Field objects have two parameters, access_bus and access_dev, determining
-respectively the access policies for the bus and core sides. They can
-take the values READ_ONLY, WRITE_ONLY and READ_WRITE.
-If the device can read, the field object provides the dev_r signal, which
-contains at all times the current value of the field (kept by the logic
-generated by Bank).
-If the device can write, the field object provides the following signals:
-  - dev_w, which provides the value to be written into the field.
-  - dev_we, which strobes the value into the field.
-
-Migen Flow (TODO)
-==========
-Many hardware acceleration problems can be expressed in the dataflow
-paradigm, that is, using a directed graph representing the flow of data
-between actors.
-
-Actors in Migen are written directly in FHDL. This maximizes the
-flexibility: for example, an actor can implement a DMA master to read
-data from system memory. It is conceivable that a CAL [7] to FHDL
-compiler be implemented at some point, to support higher level
-descriptions of some actors and reuse of third-party RVC-CAL
-applications. [8] [9] [10]
-
-Actors communicate by exchanging tokens, whose flow is typically
-controlled using handshake signals (strobe/ack).
-
-Each actor has a "scheduling model". It can be:
-  - N-sequential: the actor fires when tokens are available at all its
-    inputs, and it produces one output token after N cycles. It cannot
-    accept new input tokens until it has produced its output. A
-    multicycle integer divider would use this model.
-  - N-pipelined: similar to the sequential model, but the actor can
-    always accept new input tokens. It produces an output token N cycles
-    of latency after accepting input tokens. A pipelined multiplier would
-    use this model.
-  - Dynamic: the general case, when no simple hypothesis can be made on
-    the token flow behaviour of the actor. An actor accessing system
-    memory on a shared bus would use this model.
-
-Migen Flow automatically generates handshake logic for the first two
-scheduling models. In the third case, the FHDL descriptions for the logic
-driving the handshake signals must be provided by the actor.
-
-If sequential or pipelined actors are connected together, Migen Flow will
-attempt to find a static schedule, remove the handshake signals, optimize
-away the control logic in each actor and replace it with a centralized
-FSM implementing the static schedule.
-
-An actor can be a composition of other actors.
-
-Actor graphs are managed using the NetworkX [11] library.
-
-
-References:
-[ 1] http://milkymist.org
-[ 2] http://www.myhdl.org
-[ 3] http://milkymist.org/thesis/thesis.pdf
-[ 4] http://www.xilinx.com/publications/archives/xcell/Xcell77.pdf p30-35
-[ 5] http://cdn.opencores.org/downloads/wbspec_b4.pdf
-[ 6] http://www.ohwr.org/projects/wishbone-gen
-[ 7] http://opendf.svn.sourceforge.net/viewvc/opendf/trunk/doc/
-     GentleIntro/GentleIntro.pdf
-[ 8] http://orcc.sourceforge.net/
-[ 9] http://orc-apps.sourceforge.net/
-[10] http://opendf.sourceforge.net/
-[11] http://networkx.lanl.gov/
-
-Practical information
-=====================
 Code repository:
 https://github.com/milkymist/migen
 Experimental version of the Milkymist SoC based on Migen:
@@ -461,8 +21,17 @@ We are also on IRC: #milkymist on the Freenode network.
 Migen is free software: you can redistribute it and/or modify it under
 the terms of the GNU General Public License as published by the Free
 Software Foundation, version 3 of the License. This program is
-distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
-without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
-PARTICULAR PURPOSE. See the GNU General Public License for more details.
+distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+more details.
+
 Unless otherwise noted, Migen's source code is copyright (C) 2011-2012
-Sebastien Bourdeauducq. Authors retain ownership of their contributions.
+Sebastien Bourdeauducq. Other authors retain ownership of their
+contributions. If a submission can reasonably be considered
+independently copyrightable, it's yours and I encourage you to claim it
+with appropriate copyright notices. This submission then falls under the
+"otherwise noted" category. All submissions must use a license
+compatible with the GPL.
+
+  "Electricity! It's like magic!"
diff --git a/doc/migen.txt b/doc/migen.txt
new file mode 100644 (file)
index 0000000..6b4452c
--- /dev/null
@@ -0,0 +1,447 @@
+             Migen (Milkymist Generator)
+a Python toolbox for building complex digital hardware
+======================================================
+
+Background
+==========
+Even though the Milkymist system-on-chip [1] is technically successful,
+it suffers from several limitations stemming from its implementation in
+manually written Verilog HDL:
+
+(1) The "event-driven" paradigm of today's dominant hardware descriptions
+languages (Verilog and VHDL, collectively referred to as "V*HDL" in the
+rest of this document) is often too general. Today's FPGA architectures
+are optimized for the implementation of fully synchronous circuits. This
+means that the bulk of the code for an efficient FPGA design falls into
+three categories:
+  (a) Combinatorial statements
+  (b) Synchronous statements
+  (c) Initialization of registers at reset
+V*HDL do not follow this organization. This means that a lot of
+repetitive manual coding is needed, which brings sources of human errors,
+petty issues, and confusion for beginners:
+  - wire vs. reg in Verilog
+  - forgetting to initialize a register at reset
+  - deciding whether a combinatorial statement must go into a
+    process/always block or not
+  - simulation mismatches with combinatorial processes/always blocks
+  - and more...
+A little-known fact about FPGAs is that many of them have to ability to
+initialize their registers from the bitstream contents. This can be done
+in a portable and standard way using an "initial" block in Verilog, and
+by affecting a value at the signal declaration in VHDL. This renders an
+explicit reset signal unnecessary in practice in some cases, which opens
+the way for further design optimization. However, this form of
+initialization is entirely not synthesizable for ASIC targets, and it is
+not easy to switch between the two forms of reset using V*HDL.
+
+(2) V*HDL support for composite types is very limited. Signals having a
+record type in VHDL are unidirectional, which makes them clumsy to use
+e.g. in bus interfaces. There is no record type support in Verilog, which
+means that a lot of copy-and-paste has to be done when forwarding grouped
+signals.
+
+(3) V*HDL support for procedurally generated logic is extremely limited.
+The most advanced forms of procedural generation of synthesizable logic
+that V*HDL offers are CPP-style directives in Verilog, combinatorial
+functions, and generate statements. Nothing really fancy, and it shows.
+To give a few examples:
+  - Building highly flexible bus interconnect is not possible. Even
+arbitrating any given number of bus masters for commonplace protocols
+such as Wishbone cannot be done with the tools at V*HDL puts at our
+disposal. This requires manual recoding of parts of the arbiter to add or
+remove a master, which is tedious and often cause frustrating errors.
+Each occurence of the latter can easily cause one or two hours of lost
+productivity when combined with the long compilation times of moderately
+complex system-on-chip designs.
+  - Building a memory infrastructure (including bus interconnect, bridges
+and caches) that can automatically adapt itself at compile-time to any
+word size of the SDRAM is clumsy and tedious.
+  - Building register banks for control, status and interrupt management
+of cores can also largely benefit from automation.
+  - Many hardware acceleration problems can fit into the dataflow
+programming model. Manual dataflow implementation in V*HDL has, again, a
+lot of redundancy and potential for human errors. See the Milkymist
+texture mapping unit [3][4] for an example of this. The amount of detail
+to deal with manually also makes the design space exploration difficult,
+and therefore hinders the design of efficient architectures.
+  - Pre-computation of values, such as filter coefficients for DSP or
+even simply trigonometric tables, must often be done using external tools
+whose results are copy-and-pasted (in the best cases, automatically) into
+the V*HDL source.
+
+Enter Migen, a Python toolbox for building complex digital hardware. We
+could have designed a brand new programming language, but that would have
+been reinventing the wheel instead of being able to benefit from Python's
+rich features and immense library. The price to pay is a slightly
+cluttered syntax at times when writing descriptions in FHDL, but we
+believe this is totally acceptable, particularly when compared to VHDL
+;-)
+
+Migen is made up of several related components, which are briefly
+described below.
+
+Migen FHDL
+==========
+The Fragmented Hardware Description Language (FHDL) is the lowest layer
+of Migen. It consists of a formal system to describe signals, and
+combinatorial and synchronous statements operating on them. The formal
+system itself is low level and close to the synthesizable subset of
+Verilog, and we then rely on Python algorithms to build complex
+structures by combining FHDL elements and encapsulating them in
+"fragments".
+The FHDL module also contains a back-end to produce synthesizable
+Verilog, and some basic analysis functions. It would be possible to
+develop a VHDL back-end as well, though more difficult than for Verilog -
+we are "cheating" a bit now as Verilog provides most of the FHDL
+semantics.
+
+FHDL differs from MyHDL [2] in fundamental ways. MyHDL follows the
+event-driven paradigm of traditional HDLs (see Background, #1) while FHDL
+separates the code into combinatorial statements, synchronous statements,
+and reset values. In MyHDL, the logic is described directly in the Python
+AST. The converter to Verilog or VHDL then examines the Python AST and
+recognizes a subset of Python that it translates into V*HDL statements.
+This seriously impedes the capability of MyHDL to generate logic
+procedurally. With FHDL, you manipulate a custom AST from Python, and you
+can more easily design algorithms that operate on it.
+
+FHDL is made of several elements, which are briefly explained below.
+
+BV
+--
+The bit vector (BV) object defines if a constant or signal is signed or
+unsigned, and how many bits it has. This is useful e.g. to:
+ - determine when to perform sign extension (FHDL uses the same rules as
+Verilog).
+ - determine the size of registers.
+ - determine how many bits should be used by each value in
+concatenations.
+
+Constant
+--------
+This object should be self-explanatory. All constant objects contain a BV
+object and a value. If no BV object is specified, one will be made up
+using the following rules:
+  - If the value is positive, the BV is unsigned and has the minimum
+number of bits needed to represent the constant's value in the canonical
+base-2 system.
+  - If the value is negative, the BV is signed, and has the minimum
+number of bits needed to represent the constant's value in the canonical
+two's complement, base-2 system.
+
+Signal
+------
+The signal object represents a value that is expected to change in the
+circuit. It does exactly what Verilog's "wire" and "reg" and VHDL's
+"signal" and "variable" do.
+
+The main point of the signal object is that it is identified by its
+Python ID (as returned by the id() function), and nothing else. It is the
+responsibility of the V*HDL back-end to establish an injective mapping
+between Python IDs and the V*HDL namespace. It should perform name
+mangling to ensure this. The consequence of this is that signal objects
+can safely become members of arbitrary Python classes, or be passed as
+parameters to functions or methods that generate logic involving them.
+
+The properties of a signal object are:
+  - a bit vector description
+  - a name, used as a hint for the V*HDL back-end name mangler.
+  - a boolean "variable". If true, the signal will behave like a VHDL
+variable, or a Verilog reg that uses blocking assignment. This parameter
+only has an effect when the signal's value is modified in a synchronous
+statement.
+  - the signal's reset value. It must be an integer, and defaults to 0.
+When the signal's value is modified with a synchronous statement, the
+reset value is the initialization value of the associated register.
+When the signal is assigned to in a conditional combinatorial statement
+(If or Case), the reset value is the value that the signal has when no
+condition that causes the signal to be driven is verified. This enforces
+the absence of latches in designs. If the signal is permanently driven
+using a combinatorial statement, the reset value has no effect.
+  
+The sole purpose of the name property is to make the generated V*HDL code
+easier to understand and debug. From a purely functional point of view,
+it is perfectly OK to have several signals with the same name property.
+The back-end will generate a unique name for each object. If no name
+property is specified, Migen will analyze the code that created the
+signal object, and try to extract the variable or member name from there.
+It then uses the module name that created the signal, a underscore, and
+the variable name. For example, if we are in module "foo", the following
+statements will create one or several signal(s) named "foo_bar":
+  bar = Signal()
+  self.bar = Signal()
+  self.baz.bar = Signal()
+  bar = [Signal() for x in range(42)]
+
+Operators
+---------
+Operators are represented by the _Operator object, which generally should
+not be used directly. Instead, most FHDL objects overload the usual
+Python logic and arithmetic operators, which allows a much lighter syntax
+to be used. For example, the expression:
+  a * b + c
+is equivalent to:
+  _Operator('+', [_Operator('*', [a, b]), c])
+  
+Slices
+------
+Likewise, slices are represented by the _Slice object, which often should
+not be used in favor of the Python slice operation [x:y].
+Implicit indices using the forms [x], [x:] and [:y] are supported.
+Beware! Slices work like Python slices, not like VHDL or Verilog slices.
+The first bound is the index of the LSB and is inclusive. The second
+bound is the index of MSB and is exclusive. In V*HDL, bounds are MSB:LSB
+and both are inclusive.
+
+Concatenations
+--------------
+Concatenations are done using the Cat object. To make the syntax lighter,
+its constructor takes a variable number of arguments, which are the
+signals to be concatenated together (you can use the Python '*' operator
+to pass a list instead).
+To be consistent with slices, the first signal is connected to the bits
+with the lowest indices in the result. This is the opposite of the way
+the '{}' construct works in Verilog.
+
+Replications
+------------
+The Replicate object represents the equivalent of {count{expression}} in
+Verilog.
+
+Assignments
+-----------
+Assignments are represented with the _Assign object. Since using it
+directly would result in a cluttered syntax, the preferred technique for
+assignments is to use the eq() method provided by objects that can have a
+value assigned to them. They are signals, and their combinations with the
+slice and concatenation operators.
+As an example, the statement:
+  a[0].eq(b)
+is equivalent to:
+  _Assign(_Slice(a, 0, 1), b)
+
+If statement
+------------
+The If object takes a first parameter which must be an expression
+(combination of the Constant, Signal, _Operator, _Slice, etc. objects)
+representing the condition, then a variable number of parameters
+representing the statements (_Assign, If, Case, etc. objects) to be
+executed when the condition is verified.
+
+The If object defines a Else() method, which when called defines the
+statements to be executed when the condition is not true. Those
+statements are passed as parameters to the variadic method.
+
+For convenience, there is also a Elif() method.
+
+Example:
+If(tx_count16 == 0,
+    tx_bitcount.eq(tx_bitcount + 1),
+    If(tx_bitcount == 8,
+        self.tx.eq(1)
+    ).Elif(tx_bitcount == 9,
+        self.tx.eq(1),
+        tx_busy.eq(0)
+    ).Else(
+        self.tx.eq(tx_reg[0]),
+        tx_reg.eq(Cat(tx_reg[1:], 0))
+    )
+)
+
+Case statement
+--------------
+The Case object constructor takes as first parameter the expression to be
+tested, then a variable number of lists describing the various cases.
+
+Each list contains an expression (typically a constant) describing the
+value to be matched, followed by the statements to be executed when there
+is a match. The head of the list can be the an instance of the Default
+object.
+
+Instances
+---------
+Instance objects represent the parametrized instantiation of a V*HDL
+module, and the connection of its ports to FHDL signals. They are useful
+in a number of cases:
+  - reusing legacy or third-party V*HDL code.
+  - using special FPGA features (DCM, ICAP, ...).
+  - implementing logic that cannot be expressed with FHDL (asynchronous
+    circuits, ...).
+  - breaking down a Migen system into multiple sub-systems, possibly
+    using different clock domains.
+
+The properties of the instance object are:
+  - the type of the instance (i.e. name of the instantiated module).
+  - a list of output ports of the instantiated module. Each element of
+    the list is a pair containing a string, which is the name of the
+    module's port, and either an existing signal (on which the port will
+    be connected to) or a BV (which will cause the creation of a new
+    signal).
+  - a list of input ports (likewise).
+  - a list of (name, value) pairs for the parameters ("generics" in VHDL)
+    of the module.
+  - the name of the clock port of the module (if any). If this is
+    specified, the port will be connected to the system clock.
+  - the name of the reset port of the module (likewise).
+  - the name of the instance (can be mangled like signal names).
+
+Memories
+--------
+Memories (on-chip SRAM) are not supported, but will be soon, using a
+mechanism similar to instances. (TODO)
+
+Fragments
+---------
+A "fragment" is a unit of logic, which is composed of:
+  - a list of combinatorial statements.
+  - a list of synchronous statements.
+  - a list of instances.
+  - a list of memories.
+  - a set of pads, which are signals intended to be connected to
+    off-chip devices.
+
+Fragments can reference arbitrary signals, including signals that are
+referenced in other fragments. Fragments can be combined using the "+"
+operator, which returns a new fragment containing the concatenation of
+each pair of lists.
+
+Fragments can be passed to the back-end for conversion to Verilog.
+
+By convention, classes that generate logic implement a method called
+"get_fragment". When called, this method builds a new fragment
+implementing the desired functionality of the class, and returns it. This
+convention allows fragments to be built automatically by combining the
+fragments from all relevant objects in the local scope, by using the
+autofragment module.
+
+Migen Core Logic
+================
+Migen Core Logic is a convenience library of common logic circuits
+implemented using FHDL:
+  - a multi-cycle integer divider.
+  - a round-robin arbiter, useful to build bus arbiters.
+  - a multiplexer bank (multimux), useful to multiplex composite
+    (grouped) signals.
+  - a condition-triggered static scheduler of FHDL synchronous statements
+    (timeline).
+
+Migen Bus
+=========
+Migen Bus contains classes providing a common structure for master and
+slave interfaces of the following buses:
+  - Wishbone [5], the general purpose bus recommended by Opencores.
+  - CSR-NG, a low-bandwidth, resource-sensitive bus designed for
+    accessing the configuration and status registers of cores from
+    software.
+  - FastMemoryLink-NG, a split-transaction bus optimized for use with a
+    high-performance, out-of-order SDRAM controller. (TODO)
+
+It also provides interconnect components for these buses, such as
+arbiters and address decoders. The strength of the Migen procedurally
+generated logic can be illustrated by the following example:
+  wbcon = wishbone.InterconnectShared(
+      [cpu.ibus, cpu.dbus, ethernet.dma, audio.dma],
+      [(0, norflash.bus), (1, wishbone2fml.wishbone),
+      (3, wishbone2csr.wishbone)])
+In this example, the interconnect component generates a 4-way round-robin
+arbiter, multiplexes the master bus signals into a shared bus, determines
+that the address decoding must occur on 2 bits, and connects all slave
+interfaces to the shared bus, inserting the address decoder logic in the
+bus cycle qualification signals and multiplexing the data return path. It
+can recognize the signals in each core's bus interface thanks to the
+common structure mandated by Migen Bus. All this happens automatically,
+using only that much user code. The resulting interconnect logic can be
+retrieved using wbcon.get_fragment(), and combined with the fragments
+from the rest of the system.
+
+Migen Bank
+==========
+Migen Bank is a system comparable to wishbone-gen [6], which automates
+the creation of configuration and status register banks and
+(TODO) interrupt/event managers implemented in cores.
+
+Bank takes a description made up of a list of registers and generates
+logic implementing it with a slave interface compatible with Migen Bus.
+
+A register can be "raw", which means that the core has direct access to
+it. It also means that the register width must be less or equal to the
+bus word width. In that case, the register object provides the following
+signals:
+  - dev_r, which contains the data written from the bus interface.
+  - dev_re, which is the strobe signal for dev_r. It is active for one
+    cycle, after or during a write from the bus. dev_r is only valid when
+    dev_re is high.
+  - dev_w, which must provide at all times the value to be read from the
+    bus.
+
+Registers that are not raw are managed by Bank and contain fields. If the
+sum of the widths of all fields attached to a register exceeds the bus
+word width, the register will automatically be sliced into words of the
+maximum size and implemented at consecutive bus addresses, MSB first.
+Field objects have two parameters, access_bus and access_dev, determining
+respectively the access policies for the bus and core sides. They can
+take the values READ_ONLY, WRITE_ONLY and READ_WRITE.
+If the device can read, the field object provides the dev_r signal, which
+contains at all times the current value of the field (kept by the logic
+generated by Bank).
+If the device can write, the field object provides the following signals:
+  - dev_w, which provides the value to be written into the field.
+  - dev_we, which strobes the value into the field.
+
+Migen Flow (TODO)
+==========
+Many hardware acceleration problems can be expressed in the dataflow
+paradigm, that is, using a directed graph representing the flow of data
+between actors.
+
+Actors in Migen are written directly in FHDL. This maximizes the
+flexibility: for example, an actor can implement a DMA master to read
+data from system memory. It is conceivable that a CAL [7] to FHDL
+compiler be implemented at some point, to support higher level
+descriptions of some actors and reuse of third-party RVC-CAL
+applications. [8] [9] [10]
+
+Actors communicate by exchanging tokens, whose flow is typically
+controlled using handshake signals (strobe/ack).
+
+Each actor has a "scheduling model". It can be:
+  - N-sequential: the actor fires when tokens are available at all its
+    inputs, and it produces one output token after N cycles. It cannot
+    accept new input tokens until it has produced its output. A
+    multicycle integer divider would use this model.
+  - N-pipelined: similar to the sequential model, but the actor can
+    always accept new input tokens. It produces an output token N cycles
+    of latency after accepting input tokens. A pipelined multiplier would
+    use this model.
+  - Dynamic: the general case, when no simple hypothesis can be made on
+    the token flow behaviour of the actor. An actor accessing system
+    memory on a shared bus would use this model.
+
+Migen Flow automatically generates handshake logic for the first two
+scheduling models. In the third case, the FHDL descriptions for the logic
+driving the handshake signals must be provided by the actor.
+
+If sequential or pipelined actors are connected together, Migen Flow will
+attempt to find a static schedule, remove the handshake signals, optimize
+away the control logic in each actor and replace it with a centralized
+FSM implementing the static schedule.
+
+An actor can be a composition of other actors.
+
+Actor graphs are managed using the NetworkX [11] library.
+
+
+References:
+[ 1] http://milkymist.org
+[ 2] http://www.myhdl.org
+[ 3] http://milkymist.org/thesis/thesis.pdf
+[ 4] http://www.xilinx.com/publications/archives/xcell/Xcell77.pdf p30-35
+[ 5] http://cdn.opencores.org/downloads/wbspec_b4.pdf
+[ 6] http://www.ohwr.org/projects/wishbone-gen
+[ 7] http://opendf.svn.sourceforge.net/viewvc/opendf/trunk/doc/
+     GentleIntro/GentleIntro.pdf
+[ 8] http://orcc.sourceforge.net/
+[ 9] http://orc-apps.sourceforge.net/
+[10] http://opendf.sourceforge.net/
+[11] http://networkx.lanl.gov/
diff --git a/doc/migen_logo.svg b/doc/migen_logo.svg
new file mode 100644 (file)
index 0000000..fdb855e
--- /dev/null
@@ -0,0 +1,224 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="159.05869"
+   height="106.55"
+   id="svg3245"
+   version="1.1"
+   inkscape:version="0.48.1 r9760"
+   sodipodi:docname="migen.svg"
+   inkscape:export-filename="/home/lekernel/migen.png"
+   inkscape:export-xdpi="184.10001"
+   inkscape:export-ydpi="184.10001">
+  <defs
+     id="defs3247">
+    <linearGradient
+       id="linearGradient6093">
+      <stop
+         style="stop-color:#2ca22c;stop-opacity:0;"
+         offset="0"
+         id="stop6095" />
+      <stop
+         style="stop-color:#2ca22c;stop-opacity:1;"
+         offset="1"
+         id="stop6097" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient6047">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="0"
+         id="stop6049" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0;"
+         offset="1"
+         id="stop6051" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#a"
+       id="linearGradient6176"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.24477,0,0,0.24477,203.271,213.559)"
+       x1="150.95"
+       y1="-22.384001"
+       x2="252.2"
+       y2="204.03999" />
+    <linearGradient
+       id="a"
+       y2="150.32001"
+       gradientUnits="userSpaceOnUse"
+       y1="13.899"
+       x2="200.5"
+       x1="200.5">
+      <stop
+         style="stop-color:#fff"
+         offset=".1374"
+         id="stop7" />
+      <stop
+         style="stop-color:#509e10;stop-opacity:1;"
+         offset="1"
+         id="stop9" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#a"
+       id="linearGradient3345"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.24477,0,0,0.24477,203.271,213.559)"
+       x1="150.95"
+       y1="-22.384001"
+       x2="252.2"
+       y2="204.03999" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#a"
+       id="linearGradient3349"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.24477,0,0,0.24477,280.71427,440.33237)"
+       x1="150.95"
+       y1="-22.384001"
+       x2="252.2"
+       y2="204.03999" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient6047"
+       id="linearGradient6053"
+       x1="178.04323"
+       y1="474.42865"
+       x2="235.87062"
+       y2="474.42865"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.78422775,0,0,1,105.91918,-2.4999996)" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient6093"
+       id="linearGradient6099"
+       x1="242.87946"
+       y1="471.54514"
+       x2="289.73526"
+       y2="471.54514"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1,0,0,1.1424088,0,-67.150429)" />
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="2.8"
+     inkscape:cx="134.13698"
+     inkscape:cy="59.325232"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     showgrid="false"
+     inkscape:window-width="1916"
+     inkscape:window-height="1117"
+     inkscape:window-x="0"
+     inkscape:window-y="0"
+     inkscape:window-maximized="1"
+     showguides="true"
+     inkscape:guide-bbox="true"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0" />
+  <metadata
+     id="metadata3250">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     id="layer1"
+     transform="translate(-242.87946,-440.32929)">
+    <rect
+       style="fill:url(#linearGradient6099);fill-opacity:1;stroke:none"
+       id="rect6043"
+       width="66.843575"
+       height="23.704336"
+       x="242.87946"
+       y="459.6947" />
+    <path
+       inkscape:connector-curvature="0"
+       id="path29"
+       d="m 366.02427,471.24237 c -22.519,36.716 -73.921,29.454 -73.921,29.454 32.229,-32.229 0.16326,-57.929 0.16326,-57.929 0,0 51.973,-7.996 73.758,28.475"
+       style="font-size:18px;fill:#00ad00;fill-opacity:1;font-family:'DejaVu Sans, Arial, Sans'" />
+    <path
+       inkscape:connector-curvature="0"
+       id="path31"
+       d="m 366.02427,471.24237 c -22.519,36.716 -73.921,29.454 -73.921,29.454 32.229,-32.229 0.16326,-57.929 0.16326,-57.929 0,0 51.973,-7.996 73.758,28.475"
+       style="font-size:18px;fill:none;font-family:'DejaVu Sans, Arial, Sans'" />
+    <path
+       style="font-size:18px;font-family:'DejaVu Sans, Arial, Sans'"
+       inkscape:connector-curvature="0"
+       id="path33"
+       d="m 364.64427,470.43237 c -5.3108,8.6038 -12.825,15.435 -21.719,20.199 -7.7214,4.1357 -16.268,6.5868 -24.897,7.9228 -6.0011,0.92916 -12.11,1.2491 -18.178,1.0907 -1.8804,-0.0489 -3.76,-0.15102 -5.6339,-0.31747 -0.51696,-0.046 -1.0334,-0.0977 -1.5489,-0.15739 -0.29226,-0.0338 -0.85842,-0.11431 -0.14808,-0.0144 0.234,0.88632 0.468,1.7726 0.702,2.6592 8.3771,-8.431 15.128,-19.206 14.819,-31.472 -0.20072,-7.9507 -3.4638,-15.551 -8.2374,-21.816 -1.8852,-2.4739 -3.9815,-4.9329 -6.418,-6.8911 -0.234,0.88633 -0.46801,1.7729 -0.70201,2.6592 0.61487,-0.0942 -0.31747,0.0377 0.24551,-0.0343 0.60361,-0.0769 1.2087,-0.14221 1.814,-0.20194 2.1765,-0.21442 4.3616,-0.33925 6.5477,-0.40461 7.0088,-0.20928 14.057,0.24796 20.959,1.4953 7.9781,1.442 15.783,3.9756 22.86,7.9654 8.0388,4.532 14.777,11.012 19.535,18.924 1.0557,1.756 3.8079,0.15739 2.7476,-1.606 -5.1914,-8.6336 -12.6,-15.613 -21.408,-20.474 -7.7483,-4.275 -16.361,-6.8644 -25.074,-8.2486 -9.4825,-1.5066 -19.54,-1.944 -29.073,-0.48367 -1.1345,0.17379 -1.5874,1.9477 -0.70201,2.6592 3.0624,2.4612 5.6283,5.6205 7.7454,8.8104 4.5202,6.8118 6.9303,14.977 5.6423,23.154 -1.4588,9.2607 -7.0781,17.201 -13.551,23.715 -0.75977,0.76492 -0.53067,2.4859 0.70201,2.6592 9.9738,1.4023 20.482,0.7025 30.334,-1.1362 8.4689,-1.5805 16.759,-4.3922 24.256,-8.6664 8.6297,-4.9199 15.91,-11.93 21.128,-20.383 1.0812,-1.7514 -1.6723,-3.3482 -2.7473,-1.606 z" />
+    <path
+       inkscape:connector-curvature="0"
+       id="path35"
+       d="m 295.19427,443.74237 c 0,0 12.67,11.257 12.67,27.475 0,0 9.8236,-9.7551 23.069,0 0,0 15.098,13.305 33.229,0 0,0 -15.539,-32.087 -68.968,-27.475 z"
+       style="font-size:18px;fill:url(#linearGradient3349);fill-opacity:1;font-family:'DejaVu Sans, Arial, Sans'" />
+    <line
+       id="line39"
+       y2="471.03238"
+       x2="400.71429"
+       y1="471.03238"
+       x1="366.79425"
+       style="font-size:18px;fill:none;stroke:#000000;stroke-width:2.44770002;font-family:'DejaVu Sans, Arial, Sans'" />
+    <path
+       inkscape:connector-curvature="0"
+       id="path59"
+       d="m 344.15733,461.16448 4.84652,0"
+       style="font-size:18px;fill:none;stroke:#000000;stroke-width:2.44799995;stroke-miterlimit:4;stroke-dasharray:none;font-family:'DejaVu Sans, Arial, Sans'"
+       sodipodi:nodetypes="cc" />
+    <path
+       sodipodi:nodetypes="cc"
+       style="font-size:18px;fill:none;stroke:#000000;stroke-width:2.44799995;stroke-miterlimit:4;stroke-dasharray:none;font-family:'DejaVu Sans, Arial, Sans'"
+       d="m 344.15733,481.90109 4.84652,0"
+       id="path6037"
+       inkscape:connector-curvature="0" />
+    <text
+       xml:space="preserve"
+       style="font-size:40px;font-style:normal;font-variant:normal;font-weight:300;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Orbitron;-inkscape-font-specification:Orbitron Light"
+       x="257.14285"
+       y="537.7193"
+       id="text6055"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         id="tspan6057"
+         x="257.14285"
+         y="537.7193">migen</tspan></text>
+    <path
+       sodipodi:nodetypes="cc"
+       style="font-size:18px;fill:none;stroke:#000000;stroke-width:2.61650872;stroke-miterlimit:4;stroke-dasharray:none;font-family:'DejaVu Sans, Arial, Sans'"
+       d="m 289.42519,459.68794 14.57866,0"
+       id="path6105"
+       inkscape:connector-curvature="0" />
+    <path
+       inkscape:connector-curvature="0"
+       id="path6107"
+       d="m 289.42519,483.37763 14.57866,0"
+       style="font-size:18px;fill:none;stroke:#000000;stroke-width:2.61650872;stroke-miterlimit:4;stroke-dasharray:none;font-family:'DejaVu Sans, Arial, Sans'"
+       sodipodi:nodetypes="cc" />
+  </g>
+</svg>