Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
  • 6 commits
  • 3 files changed
  • 0 comments
  • 1 contributor
63  migen/actorlib/spi.py
@@ -4,6 +4,9 @@
4 4
 from migen.fhdl.specials import Memory
5 5
 from migen.bank.description import *
6 6
 from migen.flow.actor import *
  7
+from migen.flow.network import *
  8
+from migen.flow import plumbing
  9
+from migen.actorlib import misc
7 10
 
8 11
 # layout is a list of tuples, either:
9 12
 # - (name, nbits, [reset value], [alignment bits])
@@ -40,9 +43,10 @@ def _create_csrs_assign(layout, target, atomic, prefix=""):
40 43
 				alignment = element[3]
41 44
 			else:
42 45
 				alignment = 0
43  
-			reg = CSRStorage(nbits + alignment, reset=reset, atomic_write=atomic, name=prefix + name)
  46
+			reg = CSRStorage(nbits + alignment, reset=reset, atomic_write=atomic,
  47
+				alignment_bits=alignment, name=prefix + name)
44 48
 			csrs.append(reg)
45  
-			assigns.append(getattr(target, name).eq(reg.storage[alignment:]))
  49
+			assigns.append(getattr(target, name).eq(reg.storage))
46 50
 	return csrs, assigns
47 51
 
48 52
 (MODE_EXTERNAL, MODE_SINGLE_SHOT, MODE_CONTINUOUS) = range(3)
@@ -51,10 +55,10 @@ class SingleGenerator(Module):
51 55
 	def __init__(self, layout, mode):
52 56
 		self.source = Source(_convert_layout(layout))
53 57
 		self.busy = Signal()
54  
-		self._csrs, assigns = _create_csrs_assign(layout, self.source.payload,
55  
-		  mode != MODE_SINGLE_SHOT)
  58
+		self._csrs, assigns = _create_csrs_assign(layout, self.source.payload, mode != MODE_SINGLE_SHOT)
56 59
 		if mode == MODE_EXTERNAL:
57  
-			trigger = self.trigger = Signal()
  60
+			self.trigger = Signal()
  61
+			trigger = self.trigger
58 62
 		elif mode == MODE_SINGLE_SHOT:
59 63
 			shoot = CSR()
60 64
 			self._csrs.insert(0, shoot)
@@ -67,7 +71,7 @@ def __init__(self, layout, mode):
67 71
 			raise ValueError
68 72
 		self.comb += self.busy.eq(self.source.stb)
69 73
 		stmts = [self.source.stb.eq(trigger)] + assigns
70  
-		self.sync += [If(self.source.ack | ~self.source.stb, *stmts)]
  74
+		self.sync += If(self.source.ack | ~self.source.stb, *stmts)
71 75
 	
72 76
 	def get_csrs(self):
73 77
 		return self._csrs
@@ -76,17 +80,16 @@ class Collector(Module, AutoCSR):
76 80
 	def __init__(self, layout, depth=1024):
77 81
 		self.sink = Sink(layout)
78 82
 		self.busy = Signal()
79  
-		self._depth = depth
80  
-		self._dw = sum(len(s) for s in self.token("sink").flatten())
81  
-		
82  
-		self._r_wa = CSRStorage(bits_for(self._depth-1), write_from_dev=True)
83  
-		self._r_wc = CSRStorage(bits_for(self._depth), write_from_dev=True, atomic_write=True)
84  
-		self._r_ra = CSRStorage(bits_for(self._depth-1))
85  
-		self._r_rd = CSRStatus(self._dw)
  83
+		dw = sum(len(s) for s in self.sink.payload.flatten())
  84
+
  85
+		self._r_wa = CSRStorage(bits_for(depth-1), write_from_dev=True)
  86
+		self._r_wc = CSRStorage(bits_for(depth), write_from_dev=True, atomic_write=True)
  87
+		self._r_ra = CSRStorage(bits_for(depth-1))
  88
+		self._r_rd = CSRStatus(dw)
86 89
 		
87 90
 		###
88 91
 	
89  
-		mem = Memory(self._dw, self._depth)
  92
+		mem = Memory(dw, depth)
90 93
 		self.specials += mem
91 94
 		wp = mem.get_port(write_capable=True)
92 95
 		rp = mem.get_port()
@@ -95,8 +98,8 @@ def __init__(self, layout, depth=1024):
95 98
 			self.busy.eq(0),
96 99
 
97 100
 			If(self._r_wc.r != 0,
98  
-				self.endpoints["sink"].ack.eq(1),
99  
-				If(self.endpoints["sink"].stb,
  101
+				self.sink.ack.eq(1),
  102
+				If(self.sink.stb,
100 103
 					self._r_wa.we.eq(1),
101 104
 					self._r_wc.we.eq(1),
102 105
 					wp.we.eq(1)
@@ -106,8 +109,34 @@ def __init__(self, layout, depth=1024):
106 109
 			self._r_wc.dat_w.eq(self._r_wc.storage - 1),
107 110
 			
108 111
 			wp.adr.eq(self._r_wa.storage),
109  
-			wp.dat_w.eq(self.token("sink").raw_bits()),
  112
+			wp.dat_w.eq(self.sink.payload.raw_bits()),
110 113
 			
111 114
 			rp.adr.eq(self._r_ra.storage),
112 115
 			self._r_rd.status.eq(rp.dat_r)
113 116
 		]
  117
+
  118
+class DMAReadController(Module):
  119
+	def __init__(self, bus_accessor, mode, base_reset=0, length_reset=0):
  120
+		bus_aw = len(bus_accessor.address.payload.a)
  121
+		bus_dw = len(bus_accessor.data.payload.d)
  122
+		alignment_bits = bits_for(bus_dw//8) - 1
  123
+
  124
+		layout = [
  125
+			("length", bus_aw + alignment_bits, length_reset, alignment_bits),
  126
+			("base", bus_aw + alignment_bits, base_reset, alignment_bits)
  127
+		]
  128
+		self.generator = SingleGenerator(layout, mode)
  129
+		g = DataFlowGraph()
  130
+		g.add_pipeline(self.generator,
  131
+			misc.IntSequence(bus_aw, bus_aw),
  132
+			AbstractActor(plumbing.Buffer),
  133
+			bus_accessor,
  134
+			AbstractActor(plumbing.Buffer))
  135
+		comp_actor = CompositeActor(g)
  136
+		self.submodules += comp_actor
  137
+
  138
+		self.data = comp_actor.q
  139
+		self.busy = comp_actor.busy
  140
+		
  141
+	def get_csrs(self):
  142
+		return self.generator.get_csrs()
26  migen/bank/description.py
@@ -47,14 +47,17 @@ def do_finalize(self, busword):
47 47
 			self.simple_csrs.append(sc)
48 48
 
49 49
 class CSRStorage(_CompoundCSR):
50  
-	def __init__(self, size=1, reset=0, atomic_write=False, write_from_dev=False, name=None):
  50
+	def __init__(self, size=1, reset=0, atomic_write=False, write_from_dev=False, alignment_bits=0, name=None):
51 51
 		_CompoundCSR.__init__(self, size, name)
52  
-		self.storage = Signal(self.size, reset=reset)
  52
+		self.alignment_bits = alignment_bits
  53
+		self.storage_full = Signal(self.size, reset=reset)
  54
+		self.storage = Signal(self.size - self.alignment_bits)
  55
+		self.comb += self.storage.eq(self.storage_full[self.alignment_bits:])
53 56
 		self.atomic_write = atomic_write
54 57
 		if write_from_dev:
55 58
 			self.we = Signal()
56  
-			self.dat_w = Signal(self.size)
57  
-			self.sync += If(self.we, self.storage.eq(self.dat_w))
  59
+			self.dat_w = Signal(self.size - self.alignment_bits)
  60
+			self.sync += If(self.we, self.storage_full.eq(self.dat_w << self.alignment_bits))
58 61
 
59 62
 	def do_finalize(self, busword):
60 63
 		nwords = (self.size + busword - 1)//busword
@@ -63,20 +66,25 @@ def do_finalize(self, busword):
63 66
 		for i in reversed(range(nwords)):
64 67
 			nbits = min(self.size - i*busword, busword)
65 68
 			sc = CSR(nbits, self.name + str(i) if nwords else self.name)
  69
+			self.simple_csrs.append(sc)
66 70
 			lo = i*busword
67 71
 			hi = lo+nbits
68 72
 			# read
69  
-			self.comb += sc.w.eq(self.storage[lo:hi])
  73
+			if lo >= self.alignment_bits:
  74
+				self.comb += sc.w.eq(self.storage_full[lo:hi])
  75
+			elif hi > self.alignment_bits:
  76
+				self.comb += sc.w.eq(Cat(Replicate(0, hi - self.alignment_bits),
  77
+					self.storage_full[self.alignment_bits:hi]))
  78
+			else:
  79
+				self.comb += sc.w.eq(0)
70 80
 			# write
71 81
 			if nwords > 1 and self.atomic_write:
72 82
 				if i:
73 83
 					self.sync += If(sc.re, backstore[lo-busword:hi-busword].eq(sc.r))
74 84
 				else:
75  
-					self.sync += If(sc.re, self.storage.eq(Cat(sc.r, backstore)))
  85
+					self.sync += If(sc.re, self.storage_full.eq(Cat(sc.r, backstore)))
76 86
 			else:
77  
-				self.sync += If(sc.re, self.storage[lo:hi].eq(sc.r))
78  
-
79  
-			self.simple_csrs.append(sc)
  87
+				self.sync += If(sc.re, self.storage_full[lo:hi].eq(sc.r))
80 88
 
81 89
 def csrprefix(prefix, csrs):
82 90
 	for csr in csrs:
30  migen/flow/network.py
@@ -37,6 +37,10 @@ def add_connection(self, source_node, sink_node,
37 37
 		self.add_edge(source_node, sink_node,
38 38
 			source=source_ep, sink=sink_ep,
39 39
 			source_subr=source_subr, sink_subr=sink_subr)
  40
+
  41
+	def add_pipeline(self, *nodes):
  42
+		for n1, n2 in zip(nodes, nodes[1:]):
  43
+			self.add_connection(n1, n2)
40 44
 	
41 45
 	def del_connections(self, source_node, sink_node, data_requirements):
42 46
 		edges_to_delete = []
@@ -203,8 +207,32 @@ def elaborate(self, optimizer=None):
203 207
 class CompositeActor(Module):
204 208
 	def __init__(self, dfg):
205 209
 		dfg.elaborate()
  210
+
  211
+		# expose unconnected endpoints
  212
+		uc_eps_by_node = dict((node, get_endpoints(node)) for node in dfg)
  213
+		for u, v, d in dfg.edges_iter(data=True):
  214
+			uc_eps_u = uc_eps_by_node[u]
  215
+			source = d["source"]
  216
+			try:
  217
+				del uc_eps_u[source]
  218
+			except KeyError:
  219
+				pass
  220
+			uc_eps_v = uc_eps_by_node[v]
  221
+			sink = d["sink"]
  222
+			try:
  223
+				del uc_eps_v[sink]
  224
+			except KeyError:
  225
+				pass
  226
+		for node, uc_eps in uc_eps_by_node.items():
  227
+			for k, v in uc_eps.items():
  228
+				assert(not hasattr(self, k))
  229
+				setattr(self, k, v)
  230
+
  231
+		# generate busy signal
206 232
 		self.busy = Signal()
207  
-		self.comb += [self.busy.eq(optree("|", [node.busy for node in dfg]))]
  233
+		self.comb += self.busy.eq(optree("|", [node.busy for node in dfg]))
  234
+
  235
+		# claim ownership of sub-actors and establish connections
208 236
 		for node in dfg:
209 237
 			self.submodules += node
210 238
 		for u, v, d in dfg.edges_iter(data=True):

No commit comments for this range

Something went wrong with that request. Please try again.