Determine Migen's API surface and document compatibility summary.
authorwhitequark <whitequark@whitequark.org>
Sat, 15 Dec 2018 11:51:09 +0000 (11:51 +0000)
committerwhitequark <whitequark@whitequark.org>
Sat, 15 Dec 2018 11:52:30 +0000 (11:52 +0000)
This also reorganizes README to more clearly describe what nMigen is,
since it was getting quite outdated.

README.md
doc/COMPAT_SUMMARY.md [new file with mode: 0644]
doc/PROPOSAL.md [new file with mode: 0644]
doc/nmigen_logo.png [new file with mode: 0644]
doc/nmigen_logo.svg [new file with mode: 0644]
doc/nmigen_logo_white.png [new file with mode: 0644]
nmigen/fhdl/cd.py

index 722c03933c50f4e56e161996edc91f867e06dd73..418a7cf769eda99ac3fafaa3464cad50b2fa79a9 100644 (file)
--- a/README.md
+++ b/README.md
-This repository contains a proposal for the design of nMigen in form of an implementation. This implementation deviates from the existing design of Migen by making several observations of its drawbacks:
-
-  * Migen is strongly tailored towards Verilog, yet translation of Migen to Verilog is not straightforward, leaves much semantics implicit (e.g. signedness, width extension, combinatorial assignments, sub-signal assignments...);
-  * Hierarchical designs are useful for floorplanning and optimization, yet Migen does not support them at all;
-  * Migen's syntax is not easily composable, and something like an FSM requires extending Migen's syntax in non-orthogonal ways;
-  * Migen reimplements a lot of mature open-source tooling, such as conversion of RTL to Verilog (Yosys' Verilog backend), or simulation (Icarus Verilog, Verilator, etc.), and often lacks in features, speed, or corner case handling.
-  * Migen requires awkward specials for some FPGA features such as asynchronous resets.
-
-It also observes that Yosys' intermediate language, RTLIL, is an ideal target for Migen-style logic, as conversion of FHDL to RTLIL is essentially a 1:1 translation, with the exception of the related issues of naming and hierarchy.
-
-This proposal makes several major changes to Migen that hopefully solve all of these drawbacks:
-
-  * nMigen changes FHDL's internal representation to closely match that of RTLIL;
-  * nMigen outputs RTLIL and relies on Yosys for conversion to Verilog, EDIF, etc;
-  * nMigen uses an exact mapping between FHDL signals and RTLIL names to off-load logic simulation to Icarus Verilog, Verilator, etc;
-  * nMigen uses an uniform, composable Python eHDL;
-  * nMigen outputs hierarchical RTLIL, automatically threading signals through the hierarchy;
-  * nMigen supports asynchronous reset directly;
-  * nMigen makes driving a signal from multiple clock domains a precise, hard error.
-
-This proposal keeps in mind but does not make the following major changes:
-
-  * nMigen could be easily modified to flatten the hierarchy if a signal is driven simultaneously from multiple modules;
-  * nMigen could be easily modified to support `x` values (invalid / don't care) by relying on RTLIL's ability to directly represent them;
-  * nMigen could be easily modified to support negative edge triggered flip-flops by relying on RTLIL's ability to directly represent them;
-  * nMigen could be easily modified to track Python source locations of primitives and export them to RTLIL/Verilog through the `src` attribute, displaying the Python source locations in timing reports directly.
-
-This proposal also makes the following simplifications:
-  * Specials are eliminated. Primitives such as memory ports are represented directly, and primitives such as tristate buffers are lowered to a selectable implementation via ordinary dependency injection (`f.submodules += platform.get_tristate(triple, io)`).
-
-The internals of nMigen in this proposal are cleaned up, yet they are kept sufficiently close to Migen that \~all Migen code should be possible to run directly on nMigen using a syntactic compatibility layer.
-
-FHDL features currently missing from this implementation:
-  * self.clock_domains +=
-  * Array
-  * Memory
-  * Tristate, TSTriple
-  * Instance
-  * FSM
-  * transformers: SplitMemory, FullMemoryWE
-  * transformers: ClockDomainsRenamer
-
-`migen.genlib`, `migen.sim` and `migen.build` are missing completely.
-
-One might reasonably expect that a roundtrip through RTLIL would result in unreadable Verilog.
-However, this is not the case, e.g. consider the examples:
-
-<details>
-<summary>alu.v</summary>
-
-```verilog
-module \$1 (co, sel, a, b, o);
-  wire [17:0] _04_;
-  input [15:0] a;
-  input [15:0] b;
-  output co;
-  reg \co$next ;
-  output [15:0] o;
-  reg [15:0] \o$next ;
-  input [1:0] sel;
-  assign _04_ = $signed(+ a) + $signed(- b);
-  always @* begin
-    \o$next  = 16'h0000;
-    \co$next  = 1'h0;
-    casez ({ 1'h1, sel == 2'h2, sel == 1'h1, sel == 0'b0 })
-      4'bzzz1:
-          \o$next  = a | b;
-      4'bzz1z:
-          \o$next  = a & b;
-      4'bz1zz:
-          \o$next  = a ^ b;
-      4'b1zzz:
-          { \co$next , \o$next  } = _04_[16:0];
-    endcase
-  end
-  assign o = \o$next ;
-  assign co = \co$next ;
-endmodule
-```
-</details>
-
-<details>
-<summary>alu_hier.v</summary>
-
-```verilog
-module add(b, o, a);
-  wire [16:0] _0_;
-  input [15:0] a;
-  input [15:0] b;
-  output [15:0] o;
-  reg [15:0] \o$next ;
-  assign _0_ = a + b;
-  always @* begin
-    \o$next  = 16'h0000;
-    \o$next  = _0_[15:0];
-  end
-  assign o = \o$next ;
-endmodule
-
-module sub(b, o, a);
-  wire [16:0] _0_;
-  input [15:0] a;
-  input [15:0] b;
-  output [15:0] o;
-  reg [15:0] \o$next ;
-  assign _0_ = a - b;
-  always @* begin
-    \o$next  = 16'h0000;
-    \o$next  = _0_[15:0];
-  end
-  assign o = \o$next ;
-endmodule
-
-module top(a, b, o, add_o, sub_o, op);
-  input [15:0] a;
-  wire [15:0] add_a;
-  reg [15:0] \add_a$next ;
-  wire [15:0] add_b;
-  reg [15:0] \add_b$next ;
-  input [15:0] add_o;
-  input [15:0] b;
-  output [15:0] o;
-  reg [15:0] \o$next ;
-  input op;
-  wire [15:0] sub_a;
-  reg [15:0] \sub_a$next ;
-  wire [15:0] sub_b;
-  reg [15:0] \sub_b$next ;
-  input [15:0] sub_o;
-  add add (
-    .a(add_a),
-    .b(add_b),
-    .o(add_o)
-  );
-  sub sub (
-    .a(sub_a),
-    .b(sub_b),
-    .o(sub_o)
-  );
-  always @* begin
-    \o$next  = 16'h0000;
-    \add_a$next  = 16'h0000;
-    \add_b$next  = 16'h0000;
-    \sub_a$next  = 16'h0000;
-    \sub_b$next  = 16'h0000;
-    \add_a$next  = a;
-    \sub_a$next  = a;
-    \add_b$next  = b;
-    \sub_b$next  = b;
-    casez ({ 1'h1, op })
-      2'bz1:
-          \o$next  = sub_o;
-      2'b1z:
-          \o$next  = add_o;
-    endcase
-  end
-  assign o = \o$next ;
-  assign add_a = \add_a$next ;
-  assign add_b = \add_b$next ;
-  assign sub_a = \sub_a$next ;
-  assign sub_b = \sub_b$next ;
-endmodule
-```
-</details>
-<details>
-<summary>clkdiv.v</summary>
-
-```verilog
-module \$1 (sys_clk, o);
-  wire [16:0] _0_;
-  output o;
-  reg \o$next ;
-  input sys_clk;
-  wire sys_rst;
-  (* init = 16'hffff *)
-  reg [15:0] v = 16'hffff;
-  reg [15:0] \v$next ;
-  assign _0_ = v + 1'h1;
-  always @(posedge sys_clk)
-      v <= \v$next ;
-  always @* begin
-    \o$next  = 1'h0;
-    \v$next  = _0_[15:0];
-    \o$next  = v[15];
-    casez (sys_rst)
-      1'h1:
-          \v$next  = 16'hffff;
-    endcase
-  end
-  assign o = \o$next ;
-endmodule
-```
-</details>
-
-<details>
-<summary>arst.v</summary>
-
-```verilog
-module \$1 (o, sys_clk, sys_rst);
-  wire [16:0] _0_;
-  output o;
-  reg \o$next ;
-  input sys_clk;
-  input sys_rst;
-  (* init = 16'h0000 *)
-  reg [15:0] v = 16'h0000;
-  reg [15:0] \v$next ;
-  assign _0_ = v + 1'h1;
-  always @(posedge sys_clk or posedge sys_rst)
-    if (sys_rst)
-      v <= 16'h0000;
-    else
-      v <= \v$next ;
-  always @* begin
-    \o$next  = 1'h0;
-    \v$next  = _0_[15:0];
-    \o$next  = v[15];
-  end
-  assign o = \o$next ;
-endmodule
-```
-</details>
-
-<details>
-<summary>pmux.v</summary>
-
-```verilog
-module \$1 (c, o, s, a, b);
-  input [15:0] a;
-  input [15:0] b;
-  input [15:0] c;
-  output [15:0] o;
-  reg [15:0] \o$next ;
-  input [2:0] s;
-  always @* begin
-    \o$next  = 16'h0000;
-    casez (s)
-      3'bzz1:
-          \o$next  = a;
-      3'bz1z:
-          \o$next  = b;
-      3'b1zz:
-          \o$next  = c;
-      3'hz:
-          \o$next  = 16'h0000;
-    endcase
-  end
-  assign o = \o$next ;
-endmodule
-```
-</details>
+# nMigen
+
+## A refreshed Python toolbox for building complex digital hardware
+
+**nMigen is incomplete and undergoes rapid development. The nMigen documentation refers to features that may not be implemented yet and compatibility guarantees that may not hold yet. Use at your own risk.**
+
+Despite being faster than schematics entry, hardware design with Verilog and VHDL remains tedious and inefficient for several reasons. The event-driven model introduces issues and manual coding that are unnecessary for synchronous circuits, which represent the lion's share of today's logic designs. Counterintuitive arithmetic rules result in steeper learning curves and provide a fertile ground for subtle bugs in designs. Finally, support for procedural generation of logic (metaprogramming) through "generate" statements is very limited and restricts the ways code can be made generic, reused and organized.
+
+To address those issues, we have developed the *nMigen FHDL*, a library that replaces the event-driven paradigm with the notions of combinatorial and synchronous statements, has arithmetic rules that make integers always behave like mathematical integers, and most importantly allows the design's logic to be constructed by a Python program. This last point enables hardware designers to take advantage of the richness of the Python language—object oriented programming, function parameters, generators, operator overloading, libraries, etc.—to build well organized, reusable and elegant designs.
+
+Other nMigen libraries are built on FHDL and provide various tools such as a system-on-chip interconnect infrastructure, a dataflow programming system, a more traditional high-level synthesizer that compiles Python routines into state machines with datapaths, and a simulator that allows test benches to be written in Python.
+
+See the [doc/](doc/) folder for more technical information.
+
+nMigen is a direct descendant of [Migen](https://m-labs.hk/migen) rewritten from scratch to address many issues that became clear in the many years Migen has been used in production. nMigen provides an extensive compatibility layer that makes it possible to build and simulate most Migen designs unmodified, as well as integrate modules written for Migen and nMigen.
+
+nMigen is designed for Python 3.7 and newer. Note that nMigen is **not** spelled nMiGen.
+
+### Introduction
+
+TBD
+
+### Links
+
+TBD
+
+### License
+
+nMigen is released under the very permissive two-clause BSD license. Under the terms of this license, you are authorized to use nMigen for closed-source proprietary designs.
+
+Even though we do not require you to do so, these things are awesome, so please do them if possible:
+  * tell us that you are using nMigen
+  * put the [nMigen logo](doc/nmigen_logo.svg) on the page of a product using it, with a link to https://m-labs.hk
+  * cite nMigen in publications related to research it has helped
+  * send us feedback and suggestions for improvements
+  * send us bug reports when something goes wrong
+  * send us the modifications and improvements you have done to nMigen as pull requests on GitHub
+
+See LICENSE file for full copyright and license info.
+
+  "Electricity! It's like magic!"
diff --git a/doc/COMPAT_SUMMARY.md b/doc/COMPAT_SUMMARY.md
new file mode 100644 (file)
index 0000000..2c7051e
--- /dev/null
@@ -0,0 +1,190 @@
+Migen and nMigen compatibility summary
+======================================
+
+nMigen intends to provide as close to 100% compatibility to Migen as possible without compromising its other goals. However, Migen widely uses `*` imports, tends to expose implementation details, and in general does not have a well-defined interface. This document attempts to elucidate a well-defined Migen API surface (including, when necessary, private items that have been used downstream), and describes the intended nMigen replacements and their implementation status.
+
+API change legend:
+  - *id*: identical
+  - *obs*: removed or irreversibly changed with compatibility stub provided
+  - *obs →n*: removed or irreversibly changed with compatibility stub provided, use *n* instead
+  - *brk*: removed or irreversibly changed with no replacement provided
+  - *brk →n*: removed or irreversibly changed with no replacement provided, use *n* instead
+  - *→n*: renamed to *n*
+  - *⇒m*: merged into *m*
+  - *a=→b=*: parameter *a* renamed to *b*
+  - *a=∼*: parameter *a* removed
+  - *.a=→.b*: attribute *a* renamed to *b*
+  - *?*: no decision made yet
+
+When describing renames or replacements, `mod` refers to a 3rd-party package `mod` (no nMigen implementation provided), `.mod.item` refers to `nmigen.mod.item`, and "(import `.item`)" means that, while `item` is provided under `nmigen.mod.item`, it is aliased to, and should be imported from a shorter path for readability.
+
+Status legend:
+  - (×) Intended replacement (the API is decided on)
+  - (−) Implemented replacement (the API and compatibility shim are provided)
+  - (+) Verified replacement and/or compatibility shim (the compatibility shim is manually reviewed and has 100% coverage)
+  - (∼) No direct replacement or compatibility shim is provided
+
+Compatibility summary
+---------------------
+
+  - (×) `fhdl`
+    - (×) `bitcontainer` ⇒ `.tools`
+      - (×) `log2_int` id
+      - (×) `bits_for` id
+      - (×) `value_bits_sign` → `Value.shape`
+    - (×) `conv_output` ?
+    - (×) `decorators` ⇒ `.fhdl.xfrm`
+      Note: `transform_*` methods not considered part of public API.
+      - (∼) `ModuleTransformer` **brk**
+      - (∼) `ControlInserter` **brk**
+      - (×) `CEInserter` id, `clock_domains=`→`controls=`
+      - (×) `ResetInserter` id, `clock_domains=`→`controls=`
+      - (×) `ClockDomainsRenamer` → `DomainRenamer`, `cd_remapping=`→`domain_map=`
+    - (∼) `edif` **brk**
+    - (×) `module` **obs** → `.fhdl.dsl`
+      - (×) `FinalizeError` **obs**
+      - (×) `Module` **obs** → `.fhdl.dsl.Module`
+    - (∼) `namer` **brk**
+    - (×) `simplify` ?
+      - (×) `FullMemoryWE` ?
+      - (×) `MemoryToArray` ?
+      - (×) `SplitMemory` ?
+    - (×) `specials` **obs**
+      - (×) `Special` ?
+      - (×) `Tristate` ?
+      - (×) `TSTriple` → `.genlib.io.TSTriple`, `bits_sign=`→`shape=`
+      - (×) `Instance` ?
+      - (×) `READ_FIRST`/`WRITE_FIRST`/`NO_CHANGE` ?
+      - (×) `_MemoryPort` ?
+      - (×) `Memory` ?
+    - (×) `structure` → `.fhdl.ast`
+      - (×) `DUID` id
+      - (×) `_Value` → `Value`
+        Note: values no longer valid as keys in `dict` and `set`; use `ValueDict` and `ValueSet` instead.
+      - (×) `wrap` → `Value.wrap`
+      - (×) `_Operator` → `Operator`
+      - (×) `Mux` → `Mux`
+      - (×) `_Slice` → `Slice`, `stop=`→`end=`, `.stop`→`.end`
+      - (×) `_Part` → `Part`
+      - (×) `Cat` id, `.l`→`.operands`
+      - (×) `Replicate` → `Repl`, `v=`→`value=`, `n=`→`count=`, `.v`→`.value`, `.n`→`.count`
+      - (×) `Constant` → `Const`, `bits_sign=`→`shape=`
+      - (×) `Signal` id, `bits_sign=`→`shape=`, `attr=`→`attrs=`, `name_override=`∼, `related=`, `variable=`∼
+      - (×) `ClockSignal` id, `cd=`→`domain=`
+      - (×) `ResetSignal` id, `cd=`→`domain=`
+      - (×) `_Statement` → `Statement`
+      - (×) `_Assign` → `Assign`, `l=`→`lhs=`, `r=`→`rhs=`
+      - (×) `_check_statement` **obs** → `Statement.wrap`
+      - (×) `If` **obs** → `.fhdl.dsl.Module.If`
+      - (×) `Case` **obs** → `.fhdl.dsl.Module.Switch`
+      - (×) `_ArrayProxy` ?
+      - (×) `Array` ?
+      - (×) `ClockDomain` → `.fhdl.cd.ClockDomain`
+      - (×) `_ClockDomainList` ?
+      - (×) `SPECIAL_INPUT`/`SPECIAL_OUTPUT`/`SPECIAL_INOUT` ?
+      - (∼) `_Fragment` **brk** → `.fhdl.ir.Fragment`
+    - (×) `tools` **brk**
+      - (×) `list_signals` ?
+      - (×) `list_targets` ?
+      - (×) `list_inputs` ?
+      - (×) `group_by_targets` ?
+      - (∼) `list_special_ios` **brk**
+      - (∼) `list_clock_domains_expr` **brk**
+      - (×) `list_clock_domains` ?
+      - (×) `is_variable` ?
+      - (∼) `generate_reset` **brk**
+      - (∼) `insert_reset` **brk**
+      - (∼) `insert_resets` **brk** → `.fhdl.xfrm.ResetInserter`
+      - (∼) `lower_basics` **brk**
+      - (∼) `lower_complex_slices` **brk**
+      - (∼) `lower_complex_parts` **brk**
+      - (∼) `rename_clock_domain_expr` **brk**
+      - (∼) `rename_clock_domain` **brk** → `.fhdl.xfrm.DomainRenamer`
+      - (∼) `call_special_classmethod` **brk**
+      - (∼) `lower_specials` **brk**
+    - (×) `tracer` **brk**
+      - (×) `get_var_name` ?
+      - (×) `remove_underscore` ?
+      - (×) `get_obj_var_name` ?
+      - (×) `index_id` ?
+      - (×) `trace_back` ?
+    - (×) `verilog`
+      - (×) `DummyAttrTranslate` ?
+      - (×) `convert` **obs** → `.back.verilog.convert`
+    - (∼) `visit` **brk** → `.fhdl.xfrm`
+      - (∼) `NodeVisitor` **brk**
+      - (∼) `NodeTransformer` **brk** → `.fhdl.xfrm.ValueTransformer`/`.fhdl.xfrm.StatementTransformer`
+  - (×) `genlib`
+    - (×) `cdc` ?
+      - (×) `MultiRegImpl` ?
+      - (×) `MultiReg` id
+      - (×) `PulseSynchronizer` ?
+      - (×) `BusSynchronizer` ?
+      - (×) `GrayCounter` ?
+      - (×) `GrayDecoder` ?
+      - (×) `ElasticBuffer` ?
+      - (×) `lcm` ?
+      - (×) `Gearbox` ?
+    - (×) `coding` ?
+      - (×) `Encoder` ?
+      - (×) `PriorityEncoder` ?
+      - (×) `Decoder` ?
+      - (×) `PriorityDecoder` ?
+    - (×) `divider` ?
+      - (×) `Divider`
+    - (×) `fifo` ?
+      - (×) `SyncFIFO` ?
+      - (×) `SyncFIFOBuffered` ?
+      - (×) `AsyncFIFO` ?
+      - (×) `AsyncFIFOBuffered` ?
+      - (×) `_FIFOInterface` ?
+    - (×) `fsm` **obs**
+      - (×) `AnonymousState` **obs**
+      - (×) `NextState` **obs**
+      - (×) `NextValue` **obs**
+      - (×) `_LowerNext` **obs**
+      - (×) `FSM` **obs**
+    - (×) `io` ?
+      - (×) `DifferentialInput` ?
+      - (×) `DifferentialOutput` ?
+      - (×) `CRG` ?
+      - (×) `DDRInput` ?
+      - (×) `DDROutput` ?
+    - (×) `misc` ?
+      - (×) `split` ?
+      - (×) `displacer` ?
+      - (×) `chooser` ?
+      - (×) `timeline` ?
+      - (×) `WaitTimer` ?
+      - (×) `BitSlip` ?
+    - (×) `record` ?
+      - (×) `DIR_NONE` ?
+      - (×) `DIR_S_TO_M` ?
+      - (×) `DIR_M_TO_S` ?
+      - (×) `set_layout_parameters` ?
+      - (×) `layout_len` ?
+      - (×) `layout_get` ?
+      - (×) `layout_partial` ?
+      - (×) `Record` ?
+    - (×) `resetsync` ?
+      - (×) `AsyncResetSynchronizer` ?
+    - (×) `roundrobin` ?
+      - (×) `SP_WITHDRAW` ?
+      - (×) `SP_CE` ?
+      - (×) `RoundRobin` ?
+    - (×) `sort` ?
+      - (×) `BitonicSort` ?
+  - (×) `sim` **obs** → `.back.pysim`
+    - (∼) `core` **brk**
+    - (∼) `vcd` **brk** → `vcd`
+    Note: only items directly under `nmigen.compat.sim`, not submodules, are provided.
+    - (×) `Simulator` **brk**
+    - (×) `run_simulation` **obs** → `.back.pysim.Simulator`
+    - (×) `passive` **obs** → `.fhdl.ast.Passive`
+  - (×) `build` ?
+  - (×) `util` **obs**
+    - (×) `misc` ⇒ `.tools`
+      - (×) `flat_iteration` → `.flatten`
+      - (∼) `xdir` **brk**
+      - (∼) `gcd_multiple` **brk**
+    - (∼) `treeviz` **brk**
diff --git a/doc/PROPOSAL.md b/doc/PROPOSAL.md
new file mode 100644 (file)
index 0000000..91b8555
--- /dev/null
@@ -0,0 +1,241 @@
+*The text below is the original nMigen implementation proposal. It is provided for illustrative and historical purposes only.*
+
+This repository contains a proposal for the design of nMigen in form of an implementation. This implementation deviates from the existing design of Migen by making several observations of its drawbacks:
+
+  * Migen is strongly tailored towards Verilog, yet translation of Migen to Verilog is not straightforward, leaves much semantics implicit (e.g. signedness, width extension, combinatorial assignments, sub-signal assignments...);
+  * Hierarchical designs are useful for floorplanning and optimization, yet Migen does not support them at all;
+  * Migen's syntax is not easily composable, and something like an FSM requires extending Migen's syntax in non-orthogonal ways;
+  * Migen reimplements a lot of mature open-source tooling, such as conversion of RTL to Verilog (Yosys' Verilog backend), or simulation (Icarus Verilog, Verilator, etc.), and often lacks in features, speed, or corner case handling.
+  * Migen requires awkward specials for some FPGA features such as asynchronous resets.
+
+It also observes that Yosys' intermediate language, RTLIL, is an ideal target for Migen-style logic, as conversion of FHDL to RTLIL is essentially a 1:1 translation, with the exception of the related issues of naming and hierarchy.
+
+This proposal makes several major changes to Migen that hopefully solve all of these drawbacks:
+
+  * nMigen changes FHDL's internal representation to closely match that of RTLIL;
+  * nMigen outputs RTLIL and relies on Yosys for conversion to Verilog, EDIF, etc;
+  * nMigen uses an exact mapping between FHDL signals and RTLIL names to off-load logic simulation to Icarus Verilog, Verilator, etc;
+  * nMigen uses an uniform, composable Python eHDL;
+  * nMigen outputs hierarchical RTLIL, automatically threading signals through the hierarchy;
+  * nMigen supports asynchronous reset directly;
+  * nMigen makes driving a signal from multiple clock domains a precise, hard error.
+
+This proposal keeps in mind but does not make the following major changes:
+
+  * nMigen could be easily modified to flatten the hierarchy if a signal is driven simultaneously from multiple modules;
+  * nMigen could be easily modified to support `x` values (invalid / don't care) by relying on RTLIL's ability to directly represent them;
+  * nMigen could be easily modified to support negative edge triggered flip-flops by relying on RTLIL's ability to directly represent them;
+  * nMigen could be easily modified to track Python source locations of primitives and export them to RTLIL/Verilog through the `src` attribute, displaying the Python source locations in timing reports directly.
+
+This proposal also makes the following simplifications:
+  * Specials are eliminated. Primitives such as memory ports are represented directly, and primitives such as tristate buffers are lowered to a selectable implementation via ordinary dependency injection (`f.submodules += platform.get_tristate(triple, io)`).
+
+The internals of nMigen in this proposal are cleaned up, yet they are kept sufficiently close to Migen that \~all Migen code should be possible to run directly on nMigen using a syntactic compatibility layer.
+
+One might reasonably expect that a roundtrip through RTLIL would result in unreadable Verilog.
+However, this is not the case, e.g. consider the examples:
+
+<details>
+<summary>alu.v</summary>
+
+```verilog
+module \$1 (co, sel, a, b, o);
+  wire [17:0] _04_;
+  input [15:0] a;
+  input [15:0] b;
+  output co;
+  reg \co$next ;
+  output [15:0] o;
+  reg [15:0] \o$next ;
+  input [1:0] sel;
+  assign _04_ = $signed(+ a) + $signed(- b);
+  always @* begin
+    \o$next  = 16'h0000;
+    \co$next  = 1'h0;
+    casez ({ 1'h1, sel == 2'h2, sel == 1'h1, sel == 0'b0 })
+      4'bzzz1:
+          \o$next  = a | b;
+      4'bzz1z:
+          \o$next  = a & b;
+      4'bz1zz:
+          \o$next  = a ^ b;
+      4'b1zzz:
+          { \co$next , \o$next  } = _04_[16:0];
+    endcase
+  end
+  assign o = \o$next ;
+  assign co = \co$next ;
+endmodule
+```
+</details>
+
+<details>
+<summary>alu_hier.v</summary>
+
+```verilog
+module add(b, o, a);
+  wire [16:0] _0_;
+  input [15:0] a;
+  input [15:0] b;
+  output [15:0] o;
+  reg [15:0] \o$next ;
+  assign _0_ = a + b;
+  always @* begin
+    \o$next  = 16'h0000;
+    \o$next  = _0_[15:0];
+  end
+  assign o = \o$next ;
+endmodule
+
+module sub(b, o, a);
+  wire [16:0] _0_;
+  input [15:0] a;
+  input [15:0] b;
+  output [15:0] o;
+  reg [15:0] \o$next ;
+  assign _0_ = a - b;
+  always @* begin
+    \o$next  = 16'h0000;
+    \o$next  = _0_[15:0];
+  end
+  assign o = \o$next ;
+endmodule
+
+module top(a, b, o, add_o, sub_o, op);
+  input [15:0] a;
+  wire [15:0] add_a;
+  reg [15:0] \add_a$next ;
+  wire [15:0] add_b;
+  reg [15:0] \add_b$next ;
+  input [15:0] add_o;
+  input [15:0] b;
+  output [15:0] o;
+  reg [15:0] \o$next ;
+  input op;
+  wire [15:0] sub_a;
+  reg [15:0] \sub_a$next ;
+  wire [15:0] sub_b;
+  reg [15:0] \sub_b$next ;
+  input [15:0] sub_o;
+  add add (
+    .a(add_a),
+    .b(add_b),
+    .o(add_o)
+  );
+  sub sub (
+    .a(sub_a),
+    .b(sub_b),
+    .o(sub_o)
+  );
+  always @* begin
+    \o$next  = 16'h0000;
+    \add_a$next  = 16'h0000;
+    \add_b$next  = 16'h0000;
+    \sub_a$next  = 16'h0000;
+    \sub_b$next  = 16'h0000;
+    \add_a$next  = a;
+    \sub_a$next  = a;
+    \add_b$next  = b;
+    \sub_b$next  = b;
+    casez ({ 1'h1, op })
+      2'bz1:
+          \o$next  = sub_o;
+      2'b1z:
+          \o$next  = add_o;
+    endcase
+  end
+  assign o = \o$next ;
+  assign add_a = \add_a$next ;
+  assign add_b = \add_b$next ;
+  assign sub_a = \sub_a$next ;
+  assign sub_b = \sub_b$next ;
+endmodule
+```
+</details>
+<details>
+<summary>clkdiv.v</summary>
+
+```verilog
+module \$1 (sys_clk, o);
+  wire [16:0] _0_;
+  output o;
+  reg \o$next ;
+  input sys_clk;
+  wire sys_rst;
+  (* init = 16'hffff *)
+  reg [15:0] v = 16'hffff;
+  reg [15:0] \v$next ;
+  assign _0_ = v + 1'h1;
+  always @(posedge sys_clk)
+      v <= \v$next ;
+  always @* begin
+    \o$next  = 1'h0;
+    \v$next  = _0_[15:0];
+    \o$next  = v[15];
+    casez (sys_rst)
+      1'h1:
+          \v$next  = 16'hffff;
+    endcase
+  end
+  assign o = \o$next ;
+endmodule
+```
+</details>
+
+<details>
+<summary>arst.v</summary>
+
+```verilog
+module \$1 (o, sys_clk, sys_rst);
+  wire [16:0] _0_;
+  output o;
+  reg \o$next ;
+  input sys_clk;
+  input sys_rst;
+  (* init = 16'h0000 *)
+  reg [15:0] v = 16'h0000;
+  reg [15:0] \v$next ;
+  assign _0_ = v + 1'h1;
+  always @(posedge sys_clk or posedge sys_rst)
+    if (sys_rst)
+      v <= 16'h0000;
+    else
+      v <= \v$next ;
+  always @* begin
+    \o$next  = 1'h0;
+    \v$next  = _0_[15:0];
+    \o$next  = v[15];
+  end
+  assign o = \o$next ;
+endmodule
+```
+</details>
+
+<details>
+<summary>pmux.v</summary>
+
+```verilog
+module \$1 (c, o, s, a, b);
+  input [15:0] a;
+  input [15:0] b;
+  input [15:0] c;
+  output [15:0] o;
+  reg [15:0] \o$next ;
+  input [2:0] s;
+  always @* begin
+    \o$next  = 16'h0000;
+    casez (s)
+      3'bzz1:
+          \o$next  = a;
+      3'bz1z:
+          \o$next  = b;
+      3'b1zz:
+          \o$next  = c;
+      3'hz:
+          \o$next  = 16'h0000;
+    endcase
+  end
+  assign o = \o$next ;
+endmodule
+```
+</details>
diff --git a/doc/nmigen_logo.png b/doc/nmigen_logo.png
new file mode 100644 (file)
index 0000000..8c86fc0
Binary files /dev/null and b/doc/nmigen_logo.png differ
diff --git a/doc/nmigen_logo.svg b/doc/nmigen_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>
diff --git a/doc/nmigen_logo_white.png b/doc/nmigen_logo_white.png
new file mode 100644 (file)
index 0000000..e2944b6
Binary files /dev/null and b/doc/nmigen_logo_white.png differ
index 941a9bab3f06eed0704b74207e498e529994b11e..4d2a33bd879afc41c6bdcfae0152130f3c93e5f6 100644 (file)
@@ -60,8 +60,8 @@ class ClockDomain:
 
         self.async_reset = async_reset
 
-    def rename(self, name):
-        self.name = name
-        self.clk.name = self._name_for(name, "clk")
+    def rename(self, new_name):
+        self.name = new_name
+        self.clk.name = self._name_for(new_name, "clk")
         if self.rst is not None:
-            self.rst.name = self._name_for(name, "rst")
+            self.rst.name = self._name_for(new_name, "rst")