- (−) `Tristate` ?
- (+) `TSTriple` → `.lib.io.TSTriple`, `bits_sign=`→`shape=`
- (−) `Instance` ?
- - (−) `READ_FIRST`/`WRITE_FIRST`/`NO_CHANGE` ?
- - (−) `_MemoryPort` ?
- - (−) `Memory` ?
+ - (−) `Memory` id
+ - (−) `.get_port` **obs** → `.read_port()` + `.write_port()`
+ - (−) `_MemoryPort` **obs**
+ <br>Note: nMigen separates read and write ports.
+ - (−) `READ_FIRST`/`WRITE_FIRST` **obs**
+ <br>Note: `READ_FIRST` corresponds to `mem.read_port(transparent=False)`, and `WRITE_FIRST` to `mem.read_port(transparent=True)`.
+ - (-) `NO_CHANGE` **brk**
+ <br>Note: in designs using `NO_CHANGE`, repalce it with an asynchronous read port and logic implementing required semantics explicitly.
- (−) `structure` → `.hdl.ast`
- (+) `DUID` id
- (+) `_Value` → `Value`
shape = shape, self.value < 0
self.nbits, self.signed = shape
if not isinstance(self.nbits, int) or self.nbits < 0:
- raise TypeError("Width must be a non-negative integer")
+ raise TypeError("Width must be a non-negative integer, not '{!r}'", self.nbits)
self.value = self.normalize(self.value, shape)
def shape(self):
class SignalKey:
def __init__(self, signal):
if type(signal) is not Signal:
- raise TypeError("Object '{!r}' is not an nMigen signal")
+ raise TypeError("Object '{!r}' is not an nMigen signal".format(signal))
self.signal = signal
def __hash__(self):
def __lt__(self, other):
if type(other) is not SignalKey:
- raise TypeError("Object '{!r}' cannot be compared to a SignalKey")
+ raise TypeError("Object '{!r}' cannot be compared to a SignalKey".format(signal))
return self.signal.duid < other.signal.duid
def __repr__(self):
--- /dev/null
+import traceback
+
+from .. import tracer
+from .ast import *
+from .ir import Instance
+
+
+class Memory:
+ def __init__(self, width, depth, init=None, name=None):
+ if not isinstance(width, int) or width < 0:
+ raise TypeError("Memory width must be a non-negative integer, not '{!r}'"
+ .format(width))
+ if not isinstance(depth, int) or depth < 0:
+ raise TypeError("Memory depth must be a non-negative integer, not '{!r}'"
+ .format(depth))
+
+ tb = traceback.extract_stack(limit=2)
+ self.src_loc = (tb[0].filename, tb[0].lineno)
+
+ if name is None:
+ try:
+ name = tracer.get_var_name(depth=2)
+ except tracer.NameNotFound:
+ name = "$memory"
+ self.name = name
+
+ self.width = width
+ self.depth = depth
+ self.init = None if init is None else list(init)
+
+ def read_port(self, domain="sync", asynchronous=False, transparent=True):
+ return ReadPort(self, domain, asynchronous, transparent)
+
+ def write_port(self, domain="sync", priority=0, granularity=None):
+ if granularity is None:
+ granularity = self.width
+ if not isinstance(granularity, int) or granularity < 0 or granularity > self.width:
+ raise TypeError("Write port granularity must be a non-negative integer not greater "
+ "than memory width, not '{!r}'"
+ .format(granularity))
+ return WritePort(self, domain, priority, granularity)
+
+
+class ReadPort:
+ def __init__(self, memory, domain, asynchronous, transparent):
+ self.memory = memory
+ self.domain = domain
+ self.asynchronous = asynchronous
+ self.transparent = transparent
+
+ self.addr = Signal(max=memory.depth)
+ self.data = Signal(memory.width)
+ self.en = Signal()
+
+ def get_fragment(self, platform):
+ return Instance("$memrd",
+ p_MEMID=self.memory,
+ p_ABITS=self.addr.nbits,
+ p_WIDTH=self.data.nbits,
+ p_CLK_ENABLE=not self.asynchronous,
+ p_CLK_POLARITY=1,
+ p_TRANSPARENT=self.transparent,
+ i_CLK=ClockSignal(self.domain),
+ i_EN=self.en,
+ i_ADDR=self.addr,
+ o_DATA=self.data,
+ )
+
+class WritePort:
+ def __init__(self, memory, domain, priority, granularity):
+ self.memory = memory
+ self.domain = domain
+ self.priority = priority
+ self.granularity = granularity
+
+ self.addr = Signal(max=memory.depth)
+ self.data = Signal(memory.width)
+ self.en = Signal(memory.width // granularity)
+
+ def get_fragment(self, platform):
+ return Instance("$memwr",
+ p_MEMID=self.memory,
+ p_ABITS=self.addr.nbits,
+ p_WIDTH=self.data.nbits,
+ p_CLK_ENABLE=1,
+ p_CLK_POLARITY=1,
+ p_PRIORITY=self.priority,
+ i_CLK=ClockSignal(self.domain),
+ i_EN=Cat(Repl(en_bit, self.granularity) for en_bit in self.en),
+ i_ADDR=self.addr,
+ i_DATA=self.data,
+ )