hdl.mem: implement memories.

This commit is contained in:
whitequark 2018-12-21 01:53:32 +00:00
parent 6672ab2e3f
commit 6d9a6b5d84
4 changed files with 104 additions and 6 deletions

View file

@ -236,7 +236,7 @@ class Const(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):
@ -1067,7 +1067,7 @@ class ValueSet(_MappedKeySet):
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):
@ -1080,7 +1080,7 @@ class SignalKey:
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):

92
nmigen/hdl/mem.py Normal file
View file

@ -0,0 +1,92 @@
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,
)