Repository: m-labs/nmigen

Issue:
seperator of signal names in records causes ambiguity
When creating a `Record`, the signals inside it are named `recordname_fieldname` currently.

This makes it hard to see the hierarchy when using snake case names for records and fields as well. I.e. having a record named `some_record` with a field named `some_field` the resulting signal is called `some_record_some_field` which could also be the name of a signal in a nested record with depth 3. 

I propose to use another character for separation (for example `.`), which would lead to `some_record.some_field` in that case.

(see: https://github.com/m-labs/nmigen/blob/master/nmigen/hdl/rec.py#L75)

Discussion:
codecov[bot]: # [Codecov](https://codecov.io/gh/m-labs/nmigen/pull/50?src=pr&el=h1) Report
> Merging [#50](https://codecov.io/gh/m-labs/nmigen/pull/50?src=pr&el=desc) into [master](https://codecov.io/gh/m-labs/nmigen/commit/81ee2db1636a504d2e60fc4649db4afde8b27e4c?src=pr&el=desc) will **not change** coverage.
> The diff coverage is `100%`.

[![Impacted file tree graph](https://codecov.io/gh/m-labs/nmigen/pull/50/graphs/tree.svg?width=650&token=gOCJYWfHzR&height=150&src=pr)](https://codecov.io/gh/m-labs/nmigen/pull/50?src=pr&el=tree)

```diff
@@          Coverage Diff           @@
##           master     #50   +/-   ##
======================================
  Coverage    85.5%   85.5%           
======================================
  Files          27      27           
  Lines        3912    3912           
  Branches      764     764           
======================================
  Hits         3345    3345           
  Misses        478     478           
  Partials       89      89
```


| [Impacted Files](https://codecov.io/gh/m-labs/nmigen/pull/50?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [nmigen/hdl/rec.py](https://codecov.io/gh/m-labs/nmigen/pull/50/diff?src=pr&el=tree#diff-bm1pZ2VuL2hkbC9yZWMucHk=) | `100% <100%> (ø)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/m-labs/nmigen/pull/50?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/m-labs/nmigen/pull/50?src=pr&el=footer). Last update [81ee2db...a6d531a](https://codecov.io/gh/m-labs/nmigen/pull/50?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).


Patch:
diff --git a/nmigen/hdl/rec.py b/nmigen/hdl/rec.py
index 999c85b..f1ddbd2 100644
--- a/nmigen/hdl/rec.py
+++ b/nmigen/hdl/rec.py
@@ -72,7 +72,7 @@ class Record(Value):
         def concat(a, b):
             if a is None:
                 return b
-            return "{}_{}".format(a, b)
+            return "{}__{}".format(a, b)
 
         self.layout = Layout.wrap(layout)
         self.fields = OrderedDict()


Test patch:
diff --git a/nmigen/test/test_hdl_rec.py b/nmigen/test/test_hdl_rec.py
index 3f68247..65e8bf6 100644
--- a/nmigen/test/test_hdl_rec.py
+++ b/nmigen/test/test_hdl_rec.py
@@ -65,11 +65,11 @@ class RecordTestCase(FHDLTestCase):
             ])
         ])
 
-        self.assertEqual(repr(r), "(rec r stb data (rec r_info a b))")
+        self.assertEqual(repr(r), "(rec r stb data (rec r__info a b))")
         self.assertEqual(len(r),  35)
         self.assertIsInstance(r.stb, Signal)
-        self.assertEqual(r.stb.name, "r_stb")
-        self.assertEqual(r["stb"].name, "r_stb")
+        self.assertEqual(r.stb.name, "r__stb")
+        self.assertEqual(r["stb"].name, "r__stb")
 
     def test_unnamed(self):
         r = [Record([