a couple language improvements as discussed.

-- 
Robert Jordens.
From 0d2a74c63d520036030086960a4e69131ae909b5 Mon Sep 17 00:00:00 2001
From: Robert Jordens <jord...@gmail.com>
Date: Mon, 2 Dec 2013 17:19:32 -0700
Subject: [PATCH 1/3] migen.fhdl.size: add fiter(), fslice(), and freversed()

do not overload __len__, __iter__, __reversed__ as not all valid
expressions (ints and bools) have them. furthermore len([]) is and
should be different from flen([]) (the later raises an error). keep
__getitem__ as an exception that proves the rule ;)
---
 doc/api.rst             |  7 ++++
 migen/fhdl/size.py      | 98 ++++++++++++++++++++++++++++++++++++++++++++++++-
 migen/fhdl/std.py       |  2 +-
 migen/test/test_size.py | 45 +++++++++++++++++++++++
 4 files changed, 150 insertions(+), 2 deletions(-)
 create mode 100644 migen/test/test_size.py

diff --git a/doc/api.rst b/doc/api.rst
index 06c8a55..d49b9b7 100644
--- a/doc/api.rst
+++ b/doc/api.rst
@@ -8,6 +8,13 @@ migen API Documentation
         :members:
         :show-inheritance:
 
+:mod:`fhdl.size` Module
+------------------------------
+
+.. automodule:: migen.fhdl.size
+        :members:
+        :show-inheritance:
+
 :mod:`genlib.fifo` Module
 ------------------------------
 
diff --git a/migen/fhdl/size.py b/migen/fhdl/size.py
index a116901..e771ccc 100644
--- a/migen/fhdl/size.py
+++ b/migen/fhdl/size.py
@@ -96,7 +96,103 @@ def value_bits_sign(v):
 		bsc = map(value_bits_sign, v.choices)
 		return max(bs[0] for bs in bsc), any(bs[1] for bs in bsc)
 	else:
-		raise TypeError
+		raise TypeError("Can not calculate bit length of {} {}".format(
+			type(v), v))
 
 def flen(v):
+	"""Bit length of an expression
+
+	Parameters
+	----------
+	v : int, bool or Value
+
+	Returns
+	-------
+	int
+		Number of bits required to store `v` or available in `v`
+
+	Examples
+	--------
+	>>> flen(f.Signal(8))
+	8
+	>>> flen(0xaa)
+	8
+	"""
 	return value_bits_sign(v)[0]
+
+def fiter(v):
+	"""Bit iterator
+
+	Parameters
+	----------
+	v : int, bool or Value
+
+	Returns
+	-------
+	iter
+		Iterator over the bits in `v`
+
+	Examples
+	--------
+	>>> list(fiter(f.Signal(2))) #doctest: +ELLIPSIS
+	[<migen.fhdl.structure._Slice object at 0x...>, <migen.fhdl.structure._Slice object at 0x...>]
+	>>> list(fiter(4))
+	[0, 0, 1]
+	"""
+	if isinstance(v, (bool, int)):
+		return ((v >> i) & 1 for i in range(bits_for(v)))
+	elif isinstance(v, f.Value):
+		return (v[i] for i in range(flen(v)))
+	else:
+		raise TypeError("Can not bit-iterate {} {}".format(type(v), v))
+
+def fslice(v, s):
+	"""Bit slice
+
+	Parameters
+	----------
+	v : int, bool or Value
+	s : slice or int
+
+	Returns
+	-------
+	int or Value
+		Expression for the slice `s` of `v`.
+
+	Examples
+	--------
+	>>> fslice(Signal(2), 1) #doctest: +ELLIPSIS
+	<migen.fhdl.structure._Slice object at 0x...>
+	>>> bin(fslice(0b1101, slice(1, None, 2)))
+	'0b10'
+	"""
+	if isinstance(v, (bool, int)):
+		if isinstance(s, int):
+			s = slice(s)
+		idx = range(*s.indices(flen(v)))
+		return sum(((v>>i) & 1) << j for j, i in enumerate(idx))
+	elif isinstance(v, f.Value):
+		return v[s]
+	else:
+		raise TypeError("Can not bit-slice {} {}".format(type(v), v))
+
+def freversed(v):
+	"""Bit reverse
+
+	Parameters
+	----------
+	v : int, bool or Value
+
+	Returns
+	-------
+	int or Value
+		Expression containing the bit reversed input.
+
+	Examples
+	--------
+	>>> freversed(Signal(2)) #doctest: +ELLIPSIS
+	<migen.fhdl.structure._Slice object at 0x...>
+	>>> bin(freversed(0b1011))
+	'0b1101'
+	"""
+	return fslice(v, slice(None, None, -1))
diff --git a/migen/fhdl/std.py b/migen/fhdl/std.py
index 3a4a3de..b9ec729 100644
--- a/migen/fhdl/std.py
+++ b/migen/fhdl/std.py
@@ -1,5 +1,5 @@
 from migen.fhdl.structure import *
 from migen.fhdl.module import Module
 from migen.fhdl.specials import TSTriple, Instance, Memory
-from migen.fhdl.size import log2_int, bits_for, flen
+from migen.fhdl.size import log2_int, bits_for, flen, fiter, fslice, freversed
 from migen.fhdl.decorators import DecorateModule, InsertCE, InsertReset, RenameClockDomains
diff --git a/migen/test/test_size.py b/migen/test/test_size.py
new file mode 100644
index 0000000..07b3052
--- /dev/null
+++ b/migen/test/test_size.py
@@ -0,0 +1,45 @@
+import unittest
+
+from migen.fhdl.std import *
+
+class SignalSizeCase(unittest.TestCase):
+	def setUp(self):
+		self.i = 0xaa
+		self.j = -127
+		self.s = Signal((13, True))
+
+	def test_flen(self):
+		self.assertEqual(flen(self.s), 13)
+		self.assertEqual(flen(self.i), 8)
+		self.assertEqual(flen(self.j), 8)
+
+	def test_flen_type(self):
+		self.assertRaises(TypeError, flen, [])
+
+	def test_fiter(self):
+		for i, si in enumerate(fiter(self.s)):
+			self.assertEqual(si, self.s[i])
+		self.assertEqual(list(fiter(self.i)),
+				[(self.i >> i) & 1 for i in range(8)])
+		self.assertEqual(list(fiter(self.j)),
+				[(self.j >> i) & 1 for i in range(8)])
+
+	def test_fiter_type(self):
+		self.assertRaises(TypeError, fiter, [])
+
+	def test_fslice(self):
+		sl = slice(1, None, 2)
+		fslice(self.s, sl)
+		self.assertEqual(fslice(self.i, sl), 15)
+		self.assertEqual(fslice(self.j, sl), 8)
+
+	def test_fslice_type(self):
+		self.assertRaises(TypeError, fslice, [], 3)
+
+	def test_freversed(self):
+		freversed(self.s)
+		freversed(self.i)
+		freversed(self.j)
+
+	def test_freveseed_type(self):
+		self.assertRaises(TypeError, freversed, [])
-- 
1.8.3.2

From d1fc7a61e6b6142dd276a2712a6e98cd5b19df6a Mon Sep 17 00:00:00 2001
From: Robert Jordens <jord...@gmail.com>
Date: Mon, 2 Dec 2013 17:23:22 -0700
Subject: [PATCH 2/3] migen.fhdl.tools: move flat_iteration to migen.util.misc
 as tools imports other things

---
 migen/fhdl/module.py |  3 ++-
 migen/fhdl/tools.py  | 11 +----------
 migen/util/misc.py   | 10 ++++++++++
 3 files changed, 13 insertions(+), 11 deletions(-)

diff --git a/migen/fhdl/module.py b/migen/fhdl/module.py
index 4764abb..30e065b 100644
--- a/migen/fhdl/module.py
+++ b/migen/fhdl/module.py
@@ -4,7 +4,8 @@ from itertools import combinations
 from migen.fhdl.structure import *
 from migen.fhdl.structure import _Fragment
 from migen.fhdl.specials import Special
-from migen.fhdl.tools import flat_iteration, rename_clock_domain
+from migen.fhdl.tools import rename_clock_domain
+from migen.util.misc import flat_iteration
 
 class FinalizeError(Exception):
 	pass
diff --git a/migen/fhdl/tools.py b/migen/fhdl/tools.py
index d940759..b25280b 100644
--- a/migen/fhdl/tools.py
+++ b/migen/fhdl/tools.py
@@ -1,17 +1,8 @@
-import collections
-
 from migen.fhdl.structure import *
 from migen.fhdl.structure import _Slice, _Assign
 from migen.fhdl.visit import NodeVisitor, NodeTransformer
 from migen.fhdl.size import value_bits_sign
-
-def flat_iteration(l):
-	for element in l:
-		if isinstance(element, collections.Iterable):
-			for element2 in flat_iteration(element):
-				yield element2
-		else:
-			yield element
+from migen.util.misc import flat_iteration
 
 class _SignalLister(NodeVisitor):
 	def __init__(self):
diff --git a/migen/util/misc.py b/migen/util/misc.py
index fa04161..6846b4a 100644
--- a/migen/util/misc.py
+++ b/migen/util/misc.py
@@ -1,3 +1,13 @@
+import collections
+
+def flat_iteration(l):
+	for element in l:
+		if isinstance(element, collections.Iterable):
+			for element2 in flat_iteration(element):
+				yield element2
+		else:
+			yield element
+
 def xdir(obj, return_values=False):
 	for attr in dir(obj):
 		if attr[:2] != "__" and attr[-2:] != "__":
-- 
1.8.3.2

From 05bcd56179f4f564843636faf2cc5a7339143b79 Mon Sep 17 00:00:00 2001
From: Robert Jordens <jord...@gmail.com>
Date: Mon, 2 Dec 2013 17:23:56 -0700
Subject: [PATCH 3/3] migen.fhdl.structure: have Cat() flat_iteration-ize its
 arguments

---
 migen/fhdl/structure.py | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/migen/fhdl/structure.py b/migen/fhdl/structure.py
index a94c198..aba747b 100644
--- a/migen/fhdl/structure.py
+++ b/migen/fhdl/structure.py
@@ -4,6 +4,7 @@ import builtins
 from collections import defaultdict
 
 from migen.fhdl import tracer
+from migen.util.misc import flat_iteration
 
 class HUID:
 	__next_uid = 0
@@ -87,7 +88,7 @@ class Value(HUID):
 		elif isinstance(key, slice):
 			start, stop, step = key.indices(flen(self))
 			if step != 1:
-				return Cat(*(self[i] for i in range(start, stop, step)))
+				return Cat(self[i] for i in range(start, stop, step))
 			return _Slice(self, start, stop)
 		else:
 			raise KeyError
@@ -155,11 +156,11 @@ class Cat(Value):
 	meeting these properties. The bit length of the return value is the sum of
 	the bit lengths of the arguments::
 
-		flen(Cat(*args)) == sum(flen(arg) for arg in args)
+		flen(Cat(args)) == sum(flen(arg) for arg in args)
 
 	Parameters
 	----------
-	*args : Value, inout
+	*args : Values or iterables of Values, inout
 		`Value` s to be concatenated.
 
 	Returns
@@ -169,7 +170,7 @@ class Cat(Value):
 	"""
 	def __init__(self, *args):
 		Value.__init__(self)
-		self.l = args
+		self.l = list(flat_iteration(args))
 
 class Replicate(Value):
 	"""Replicate a value
-- 
1.8.3.2

_______________________________________________
Devel mailing list
Devel@lists.milkymist.org
https://ssl.serverraum.org/lists/listinfo/devel

Reply via email to