Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: m-labs/nmigen
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 51269ad4a037
Choose a base ref
...
head repository: m-labs/nmigen
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 8b05b28f5a7c
Choose a head ref
  • 2 commits
  • 2 files changed
  • 1 contributor

Commits on Oct 26, 2019

  1. Copy the full SHA
    ffd10e3 View commit details
  2. back.rtlil: avoid exponential behavior when legalizing Part().

    Fixes #259.
    whitequark committed Oct 26, 2019
    Copy the full SHA
    8b05b28 View commit details
Showing with 43 additions and 2 deletions.
  1. +30 −0 examples/basic/sel.py
  2. +13 −2 nmigen/back/rtlil.py
30 changes: 30 additions & 0 deletions examples/basic/sel.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
from types import SimpleNamespace
from nmigen import *
from nmigen.cli import main


class FlatGPIO(Elaboratable):
def __init__(self, pins, bus):
self.pins = pins
self.bus = bus

def elaborate(self, platform):
bus = self.bus

m = Module()
m.d.comb += bus.r_data.eq(self.pins.word_select(bus.addr, len(bus.r_data)))
with m.If(bus.we):
m.d.sync += self.pins.word_select(bus.addr, len(bus.w_data)).eq(bus.w_data)
return m


if __name__ == "__main__":
bus = Record([
("addr", 3),
("r_data", 2),
("w_data", 2),
("we", 1),
])
pins = Signal(8)
gpio = FlatGPIO(pins, bus)
main(gpio, ports=[pins, bus.addr, bus.r_data, bus.w_data, bus.we])
15 changes: 13 additions & 2 deletions nmigen/back/rtlil.py
Original file line number Diff line number Diff line change
@@ -622,9 +622,20 @@ def _prepare_value_for_Slice(self, value):
def on_Part(self, value):
offset = self.s.expand(value.offset)
if isinstance(offset, ast.Const):
return self(ast.Slice(value.value, offset.value, offset.value + value.width))
if offset.value == len(value.value):
dummy_wire = self.s.rtlil.wire(value.width)
return dummy_wire
return self(ast.Slice(value.value,
offset.value * value.stride,
offset.value * value.stride + value.width))
else:
raise LegalizeValue(value.offset, range((1 << len(value.offset))), value.src_loc)
# Only so many possible parts. The amount of branches is exponential; if value.offset
# is large (e.g. 32-bit wide), trying to naively legalize it is likely to exhaust
# system resources.
max_branches = len(value.value) // value.stride + 1
raise LegalizeValue(value.offset,
range((1 << len(value.offset)) // value.stride)[:max_branches],
value.src_loc)

def on_Repl(self, value):
raise TypeError # :nocov: