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: b09f4b10ee68
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: 3e59d857e17f
Choose a head ref
  • 2 commits
  • 3 files changed
  • 1 contributor

Commits on Dec 14, 2018

  1. setup: add missing import.

    whitequark committed Dec 14, 2018
    Copy the full SHA
    55e729f View commit details
  2. Copy the full SHA
    3e59d85 View commit details
Showing with 43 additions and 35 deletions.
  1. +32 −30 nmigen/back/pysim.py
  2. +10 −5 nmigen/fhdl/ast.py
  3. +1 −0 setup.py
62 changes: 32 additions & 30 deletions nmigen/back/pysim.py
Original file line number Diff line number Diff line change
@@ -21,20 +21,20 @@ def get(self, signal):
return self.curr[signal]

def set_curr(self, signal, value):
assert isinstance(value, Const)
if self.curr[signal].value != value.value:
assert isinstance(value, int)
if self.curr[signal] != value:
self.curr_dirty.add(signal)
self.curr[signal] = value

def set_next(self, signal, value):
assert isinstance(value, Const)
if self.next[signal].value != value.value:
assert isinstance(value, int)
if self.next[signal] != value:
self.next_dirty.add(signal)
self.next[signal] = value

def commit(self, signal):
old_value = self.curr[signal]
if self.curr[signal].value != self.next[signal].value:
if self.curr[signal] != self.next[signal]:
self.next_dirty.remove(signal)
self.curr_dirty.add(signal)
self.curr[signal] = self.next[signal]
@@ -47,12 +47,15 @@ def iter_dirty(self):
yield signal, self.curr[signal], self.next[signal]


normalize = Const.normalize


class _RHSValueCompiler(ValueTransformer):
def __init__(self, sensitivity):
self.sensitivity = sensitivity

def on_Const(self, value):
return lambda state: value
return lambda state: value.value

def on_Signal(self, value):
self.sensitivity.add(value)
@@ -69,36 +72,35 @@ def on_Operator(self, value):
if len(value.operands) == 1:
arg, = map(self, value.operands)
if value.op == "~":
return lambda state: Const(~arg(state).value, shape)
elif value.op == "-":
return lambda state: Const(-arg(state).value, shape)
return lambda state: normalize(~arg(state), shape)
if value.op == "-":
return lambda state: normalize(-arg(state), shape)
elif len(value.operands) == 2:
lhs, rhs = map(self, value.operands)
if value.op == "+":
return lambda state: Const(lhs(state).value + rhs(state).value, shape)
return lambda state: normalize(lhs(state) + rhs(state), shape)
if value.op == "-":
return lambda state: Const(lhs(state).value - rhs(state).value, shape)
return lambda state: normalize(lhs(state) - rhs(state), shape)
if value.op == "&":
return lambda state: Const(lhs(state).value & rhs(state).value, shape)
return lambda state: normalize(lhs(state) & rhs(state), shape)
if value.op == "|":
return lambda state: Const(lhs(state).value | rhs(state).value, shape)
return lambda state: normalize(lhs(state) | rhs(state), shape)
if value.op == "^":
return lambda state: Const(lhs(state).value ^ rhs(state).value, shape)
elif value.op == "==":
lhs, rhs = map(self, value.operands)
return lambda state: Const(lhs(state).value == rhs(state).value, shape)
return lambda state: normalize(lhs(state) ^ rhs(state), shape)
if value.op == "==":
return lambda state: normalize(lhs(state) == rhs(state), shape)
elif len(value.operands) == 3:
if value.op == "m":
sel, val1, val0 = map(self, value.operands)
return lambda state: val1(state) if sel(state).value else val0(state)
return lambda state: val1(state) if sel(state) else val0(state)
raise NotImplementedError("Operator '{}' not implemented".format(value.op))

def on_Slice(self, value):
shape = value.shape()
arg = self(value.value)
shift = value.start
mask = (1 << (value.end - value.start)) - 1
return lambda state: Const((arg(state).value >> shift) & mask, shape)
return lambda state: normalize((arg(state) >> shift) & mask, shape)

def on_Part(self, value):
raise NotImplementedError
@@ -113,8 +115,8 @@ def on_Cat(self, value):
def eval(state):
result = 0
for offset, mask, opnd in parts:
result |= (opnd(state).value & mask) << offset
return Const(result, shape)
result |= (opnd(state) & mask) << offset
return normalize(result, shape)
return eval

def on_Repl(self, value):
@@ -127,8 +129,8 @@ def eval(state):
result = 0
for _ in range(count):
result <<= offset
result |= opnd(state).value
return Const(result, shape)
result |= opnd(state)
return normalize(result, shape)
return eval


@@ -147,7 +149,7 @@ def on_Assign(self, stmt):
lhs = self.lhs_compiler(stmt.lhs)
rhs = self.rhs_compiler(stmt.rhs)
def run(state):
lhs(state, Const(rhs(state).value, shape))
lhs(state, normalize(rhs(state), shape))
return run

def on_Switch(self, stmt):
@@ -164,7 +166,7 @@ def on_Switch(self, stmt):
cases.append((lambda test: test & mask == value,
self.on_statements(stmts)))
def run(state):
test_value = test(state).value
test_value = test(state)
for check, body in cases:
if check(test_value):
body(state)
@@ -255,7 +257,7 @@ def __enter__(self):
self._signals.add(signal)

self._state.curr[signal] = self._state.next[signal] = \
Const(signal.reset, signal.shape())
normalize(signal.reset, signal.shape())
self._state.curr_dirty.add(signal)

if signal not in self._vcd_signals:
@@ -295,15 +297,15 @@ def __enter__(self):

def _commit_signal(self, signal):
old, new = self._state.commit(signal)
if old.value == 0 and new.value == 1 and signal in self._domain_triggers:
if (old, new) == (0, 1) and signal in self._domain_triggers:
domain = self._domain_triggers[signal]
for sync_signal in self._state.next_dirty:
if sync_signal in self._domain_signals[domain]:
self._commit_signal(sync_signal)

if self._vcd_writer:
for vcd_signal in self._vcd_signals[signal]:
self._vcd_writer.change(vcd_signal, self._timestamp * 1e10, new.value)
self._vcd_writer.change(vcd_signal, self._timestamp * 1e10, new)

def _handle_event(self):
handlers = set()
@@ -320,7 +322,7 @@ def _handle_event(self):
self._commit_signal(signal)

def _force_signal(self, signal, value):
assert signal in self._comb_signals or signal in self._user_signals
assert signal in self._user_signals
self._state.set_next(signal, value)
self._commit_signal(signal)

@@ -339,7 +341,7 @@ def _run_process(self, proc):
elif isinstance(stmt, Assign):
assert isinstance(stmt.lhs, Signal)
assert isinstance(stmt.rhs, Const)
self._force_signal(stmt.lhs, Const(stmt.rhs.value, stmt.lhs.shape()))
self._force_signal(stmt.lhs, normalize(stmt.rhs.value, stmt.lhs.shape()))
else:
raise TypeError("Received unsupported statement '{!r}' from process {}"
.format(stmt, proc))
15 changes: 10 additions & 5 deletions nmigen/fhdl/ast.py
Original file line number Diff line number Diff line change
@@ -218,6 +218,15 @@ class Const(Value):
"""
src_loc = None

@staticmethod
def normalize(value, shape):
nbits, signed = shape
mask = (1 << nbits) - 1
value &= mask
if signed and value >> (nbits - 1):
value |= ~mask
return value

def __init__(self, value, shape=None):
self.value = int(value)
if shape is None:
@@ -227,11 +236,7 @@ def __init__(self, value, shape=None):
self.nbits, self.signed = shape
if not isinstance(self.nbits, int) or self.nbits < 0:
raise TypeError("Width must be a positive integer")

mask = (1 << self.nbits) - 1
self.value &= mask
if self.signed and self.value >> (self.nbits - 1):
self.value |= ~mask
self.value = self.normalize(self.value, shape)

def shape(self):
return self.nbits, self.signed
1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import sys
from setuptools import setup, find_packages