support re-slicing and non-unit step size

* support slicing of Slice/Cat/Replicate through lowering
* support non-unit step size slices through unpacking and Cat()
This commit is contained in:
Robert Jördens 2013-06-27 13:31:00 -06:00 committed by Sebastien Bourdeauducq
parent 9d241f8cd3
commit a255296171
3 changed files with 30 additions and 10 deletions

16
examples/basic/reslice.py Normal file
View file

@ -0,0 +1,16 @@
from migen.fhdl.std import *
from migen.fhdl import verilog
class Example(Module):
def __init__(self):
a = Signal(3)
b = Signal(4)
c = Signal(5)
d = Signal(7)
s1 = c[:3][:2]
s2 = Cat(a, b)[:6]
s3 = Cat(s1, s2)[-5:]
self.comb += s3.eq(0)
self.comb += d.eq(Cat(d[::-1], Cat(s1[:1], s3[-4:])[:3]))
print(verilog.convert(Example()))

View file

@ -75,16 +75,9 @@ class Value(HUID):
key += flen(self)
return _Slice(self, key, key+1)
elif isinstance(key, slice):
start = key.start or 0
stop = key.stop or flen(self)
if start < 0:
start += flen(self)
if stop < 0:
stop += flen(self)
if stop > flen(self):
stop = flen(self)
if key.step != None:
raise KeyError
start, stop, step = key.indices(flen(self))
if step != 1:
return Cat(*(self[i] for i in range(start, stop, step)))
return _Slice(self, start, stop)
else:
raise KeyError

View file

@ -163,6 +163,17 @@ class _BasicLowerer(NodeTransformer):
def visit_ResetSignal(self, node):
return self.clock_domains[node.cd].rst
def visit_Slice(self, node):
if not isinstance(node.value, Signal):
slice_proxy = Signal(value_bits_sign(node.value))
if self.target_context:
a = _Assign(node.value, slice_proxy)
else:
a = _Assign(slice_proxy, node.value)
self.comb.append(self.visit_Assign(a))
node = _Slice(slice_proxy, node.start, node.stop)
return NodeTransformer.visit_Slice(self, node)
def lower_basics(f):
bl = _BasicLowerer(f.clock_domains)
f = bl.visit(f)