Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
  • 3 commits
  • 13 files changed
  • 0 comments
  • 1 contributor
24  examples/basic/record.py
... ...
@@ -0,0 +1,24 @@
  1
+from migen.fhdl.structure import *
  2
+from migen.fhdl.module import Module
  3
+from migen.fhdl import verilog
  4
+from migen.genlib.record import *
  5
+
  6
+L = [
  7
+	("position", [
  8
+			("x", 10, DIR_M_TO_S),
  9
+			("y", 10, DIR_M_TO_S),
  10
+	]),
  11
+	("color", 32, DIR_M_TO_S),
  12
+	("stb", 1, DIR_M_TO_S),
  13
+	("ack", 1, DIR_S_TO_M)
  14
+]
  15
+
  16
+class Test(Module):
  17
+	def __init__(self):
  18
+		master = Record(L)
  19
+		slave = Record(L)
  20
+		self.comb += master.connect(slave)
  21
+
  22
+print(verilog.convert(Test()))
  23
+print(layout_len(L))
  24
+print(layout_partial(L, "position/x", "color"))
20  examples/basic/using_record.py
... ...
@@ -1,20 +0,0 @@
1  
-from migen.fhdl.structure import *
2  
-from migen.genlib.record import *
3  
-
4  
-L = [
5  
-	("x", 10, 8),
6  
-	("y", 10, 8),
7  
-	("level2", [
8  
-		("a", 5, 32),
9  
-		("b", 5, 16)
10  
-	])
11  
-]
12  
-
13  
-myrec = Record(L)
14  
-print(myrec.flatten())
15  
-print(myrec.flatten(True))
16  
-s = myrec.subrecord("level2/a", "x")
17  
-print(s.flatten())
18  
-print(s.level2.layout())
19  
-myrec2 = myrec.copy()
20  
-print(myrec2.flatten())
2  migen/actorlib/spi.py
@@ -108,7 +108,7 @@ def get_fragment(self):
108 108
 			self._r_wc.dat_w.eq(self._r_wc.storage - 1),
109 109
 			
110 110
 			wp.adr.eq(self._r_wa.storage),
111  
-			wp.dat_w.eq(Cat(*self.token("sink").flatten())),
  111
+			wp.dat_w.eq(self.token("sink").raw_bits()),
112 112
 			
113 113
 			rp.adr.eq(self._r_ra.storage),
114 114
 			self._r_rd.status.eq(rp.dat_r)
6  migen/actorlib/structuring.py
@@ -29,7 +29,7 @@ def get_process_fragment(self):
29 29
 		])
30 30
 
31 31
 def pack_layout(l, n):
32  
-	return [("chunk{0}".format(i), l) for i in range(n)]
  32
+	return [("chunk"+str(i), l) for i in range(n)]
33 33
 
34 34
 class Unpack(Actor):
35 35
 	def __init__(self, n, layout_to):
@@ -57,7 +57,7 @@ def get_fragment(self):
57 57
 		]
58 58
 		cases = {}
59 59
 		for i in range(self.n):
60  
-			cases[i] = [Cat(*self.token("source").flatten()).eq(Cat(*self.token("sink").subrecord("chunk{0}".format(i)).flatten()))]
  60
+			cases[i] = [self.token("source").raw_bits().eq(getattr(self.token("sink"), "chunk"+str(i)).raw_bits())]
61 61
 		comb.append(Case(mux, cases).makedefault())
62 62
 		return Fragment(comb, sync)
63 63
 
@@ -75,7 +75,7 @@ def get_fragment(self):
75 75
 		strobe_all = Signal()
76 76
 		cases = {}
77 77
 		for i in range(self.n):
78  
-			cases[i] = [Cat(*self.token("source").subrecord("chunk{0}".format(i)).flatten()).eq(*self.token("sink").flatten())]
  78
+			cases[i] = [getattr(self.token("source"), "chunk"+str(i)).raw_bits().eq(self.token("sink").raw_bits())]
79 79
 		comb = [
80 80
 			self.busy.eq(strobe_all),
81 81
 			self.endpoints["sink"].ack.eq(~strobe_all | self.endpoints["source"].ack),
103  migen/bus/csr.py
... ...
@@ -1,23 +1,24 @@
1 1
 from migen.fhdl.structure import *
2 2
 from migen.fhdl.specials import Memory
3 3
 from migen.fhdl.module import Module
4  
-from migen.bus.simple import *
5 4
 from migen.bus.transactions import *
6 5
 from migen.bank.description import CSRStorage
  6
+from migen.genlib.record import *
7 7
 from migen.genlib.misc import chooser
8 8
 
9 9
 data_width = 8
10 10
 
11  
-class Interface(SimpleInterface):
  11
+class Interface(Record):
12 12
 	def __init__(self):
13  
-		SimpleInterface.__init__(self, Description(
14  
-			(M_TO_S,	"adr",		14),
15  
-			(M_TO_S,	"we",		1),
16  
-			(M_TO_S,	"dat_w",	data_width),
17  
-			(S_TO_M,	"dat_r",	data_width)))
  13
+		Record.__init__(self, [
  14
+			("adr",		14,			DIR_M_TO_S),
  15
+			("we",		1,			DIR_M_TO_S),
  16
+			("dat_w",	data_width,	DIR_M_TO_S),
  17
+			("dat_r",	data_width,	DIR_S_TO_M)])
18 18
 
19  
-class Interconnect(SimpleInterconnect):
20  
-	pass
  19
+class Interconnect(Module):
  20
+	def __init__(self, master, slaves):
  21
+		self.comb += master.connect(*slaves)
21 22
 
22 23
 class Initiator(Module):
23 24
 	def __init__(self, generator, bus=None):
@@ -53,80 +54,74 @@ def _compute_page_bits(nwords):
53 54
 	else:
54 55
 		return 0
55 56
 
56  
-class SRAM:
  57
+class SRAM(Module):
57 58
 	def __init__(self, mem_or_size, address, read_only=None, bus=None):
58 59
 		if isinstance(mem_or_size, Memory):
59  
-			self.mem = mem_or_size
  60
+			mem = mem_or_size
60 61
 		else:
61  
-			self.mem = Memory(data_width, mem_or_size//(data_width//8))
62  
-		self.address = address
63  
-		if self.mem.width > data_width:
64  
-			self.csrw_per_memw = (self.mem.width + data_width - 1)//data_width
65  
-			self.word_bits = bits_for(self.csrw_per_memw-1)
  62
+			mem = Memory(data_width, mem_or_size//(data_width//8))
  63
+		if mem.width > data_width:
  64
+			csrw_per_memw = (self.mem.width + data_width - 1)//data_width
  65
+			word_bits = bits_for(csrw_per_memw-1)
66 66
 		else:
67  
-			self.csrw_per_memw = 1
68  
-			self.word_bits = 0
69  
-		page_bits = _compute_page_bits(self.mem.depth + self.word_bits)
  67
+			csrw_per_memw = 1
  68
+			word_bits = 0
  69
+		page_bits = _compute_page_bits(mem.depth + word_bits)
70 70
 		if page_bits:
71 71
 			self._page = CSRStorage(page_bits, name=self.mem.name_override + "_page")
72 72
 		else:
73 73
 			self._page = None
74 74
 		if read_only is None:
75  
-			if hasattr(self.mem, "bus_read_only"):
76  
-				read_only = self.mem.bus_read_only
  75
+			if hasattr(mem, "bus_read_only"):
  76
+				read_only = mem.bus_read_only
77 77
 			else:
78 78
 				read_only = False
79  
-		self.read_only = read_only
80 79
 		if bus is None:
81 80
 			bus = Interface()
82 81
 		self.bus = bus
83 82
 	
84  
-	def get_csrs(self):
85  
-		if self._page is None:
86  
-			return []
87  
-		else:
88  
-			return [self._page]
89  
-	
90  
-	def get_fragment(self):
91  
-		port = self.mem.get_port(write_capable=not self.read_only,
92  
-			we_granularity=data_width if not self.read_only and self.word_bits else 0)
  83
+		###
  84
+
  85
+		self.specials += mem
  86
+		port = mem.get_port(write_capable=not read_only,
  87
+			we_granularity=data_width if not read_only and word_bits else 0)
93 88
 		
94 89
 		sel = Signal()
95 90
 		sel_r = Signal()
96  
-		sync = [sel_r.eq(sel)]
97  
-		comb = [sel.eq(self.bus.adr[9:] == self.address)]
  91
+		self.sync += sel_r.eq(sel)
  92
+		self.comb += sel.eq(self.bus.adr[9:] == address)
98 93
 
99  
-		if self.word_bits:
100  
-			word_index = Signal(self.word_bits)
101  
-			word_expanded = Signal(self.csrw_per_memw*data_width)
102  
-			sync.append(word_index.eq(self.bus.adr[:self.word_bits]))
103  
-			comb += [
  94
+		if word_bits:
  95
+			word_index = Signal(word_bits)
  96
+			word_expanded = Signal(csrw_per_memw*data_width)
  97
+			sync.append(word_index.eq(self.bus.adr[:word_bits]))
  98
+			self.comb += [
104 99
 				word_expanded.eq(port.dat_r),
105 100
 				If(sel_r,
106  
-					chooser(word_expanded, word_index, self.bus.dat_r, n=self.csrw_per_memw, reverse=True)
  101
+					chooser(word_expanded, word_index, self.bus.dat_r, n=csrw_per_memw, reverse=True)
107 102
 				)
108 103
 			]
109  
-			if not self.read_only:
110  
-				comb += [
111  
-					If(sel & self.bus.we, port.we.eq((1 << self.word_bits) >> self.bus.adr[:self.word_bits])),
112  
-					port.dat_w.eq(Replicate(self.bus.dat_w, self.csrw_per_memw))
  104
+			if not read_only:
  105
+				self.comb += [
  106
+					If(sel & self.bus.we, port.we.eq((1 << word_bits) >> self.bus.adr[:self.word_bits])),
  107
+					port.dat_w.eq(Replicate(self.bus.dat_w, csrw_per_memw))
113 108
 				]
114 109
 		else:
115  
-			comb += [
116  
-				If(sel_r,
117  
-					self.bus.dat_r.eq(port.dat_r)
118  
-				)
119  
-			]
120  
-			if not self.read_only:
121  
-				comb += [
  110
+			self.comb += If(sel_r, self.bus.dat_r.eq(port.dat_r))
  111
+			if not read_only:
  112
+				self.comb += [
122 113
 					port.we.eq(sel & self.bus.we),
123 114
 					port.dat_w.eq(self.bus.dat_w)
124 115
 				]
125 116
 		
126 117
 		if self._page is None:
127  
-			comb.append(port.adr.eq(self.bus.adr[self.word_bits:len(port.adr)]))
  118
+			self.comb += port.adr.eq(self.bus.adr[word_bits:len(port.adr)])
128 119
 		else:
129 120
 			pv = self._page.storage
130  
-			comb.append(port.adr.eq(Cat(self.bus.adr[self.word_bits:len(port.adr)-len(pv)], pv)))
131  
-		
132  
-		return Fragment(comb, sync, specials={self.mem})
  121
+			self.comb += port.adr.eq(Cat(self.bus.adr[word_bits:len(port.adr)-len(pv)], pv))
  122
+
  123
+	def get_csrs(self):
  124
+		if self._page is None:
  125
+			return []
  126
+		else:
  127
+			return [self._page]
62  migen/bus/dfi.py
... ...
@@ -1,29 +1,31 @@
1 1
 from migen.fhdl.structure import *
2  
-from migen.bus.simple import *
  2
+from migen.fhdl.module import Module
  3
+from migen.genlib.record import *
3 4
 
4 5
 def phase_description(a, ba, d):
5  
-	return Description(
6  
-		(M_TO_S,	"address",	a),
7  
-		(M_TO_S,	"bank",		ba),
8  
-		(M_TO_S,	"cas_n",	1),
9  
-		(M_TO_S,	"cke",		1),
10  
-		(M_TO_S,	"cs_n",		1),
11  
-		(M_TO_S,	"ras_n",	1),
12  
-		(M_TO_S,	"we_n",		1),
  6
+	return [
  7
+		("address",			a,		DIR_M_TO_S),	
  8
+		("bank",			ba,		DIR_M_TO_S),
  9
+		("cas_n",			1,		DIR_M_TO_S),
  10
+		("cke",				1,		DIR_M_TO_S),
  11
+		("cs_n",			1,		DIR_M_TO_S),
  12
+		("ras_n",			1,		DIR_M_TO_S),
  13
+		("we_n",			1,		DIR_M_TO_S),
13 14
 		
14  
-		(M_TO_S,	"wrdata",	d),
15  
-		(M_TO_S,	"wrdata_en",	1),
16  
-		(M_TO_S,	"wrdata_mask",	d//8),
  15
+		("wrdata",			d,		DIR_M_TO_S),
  16
+		("wrdata_en",		1,		DIR_M_TO_S),
  17
+		("wrdata_mask",		d//8,	DIR_M_TO_S),
17 18
 		
18  
-		(M_TO_S,	"rddata_en",	1),
19  
-		(S_TO_M,	"rddata",	d),
20  
-		(S_TO_M,	"rddata_valid",	1)
21  
-	)
  19
+		("rddata_en",		1,		DIR_M_TO_S),
  20
+		("rddata",			d,		DIR_S_TO_M),
  21
+		("rddata_valid",	1,		DIR_S_TO_M)
  22
+	]
22 23
 
23  
-class Interface:
  24
+class Interface(Record):
24 25
 	def __init__(self, a, ba, d, nphases=1):
25  
-		self.pdesc = phase_description(a, ba, d)
26  
-		self.phases = [SimpleInterface(self.pdesc) for i in range(nphases)]
  26
+		layout = [("p"+str(i), phase_description(a, ba, d)) for i in range(nphases)]
  27
+		Record.__init__(self, layout)
  28
+		self.phases = [getattr(self, "p"+str(i)) for i in range(nphases)]
27 29
 		for p in self.phases:
28 30
 			p.cas_n.reset = 1
29 31
 			p.cs_n.reset = 1
@@ -35,28 +37,18 @@ def get_standard_names(self, m2s=True, s2m=True):
35 37
 		r = []
36 38
 		add_suffix = len(self.phases) > 1
37 39
 		for n, phase in enumerate(self.phases):
38  
-			for signal in self.pdesc.desc:
39  
-				if (m2s and signal[0] == M_TO_S) or (s2m and signal[0] == S_TO_M):
  40
+			for field, size, direction in phase.layout:
  41
+				if (m2s and direction == DIR_M_TO_S) or (s2m and direction == DIR_S_TO_M):
40 42
 					if add_suffix:
41  
-						if signal[0] == M_TO_S:
  43
+						if direction == DIR_M_TO_S:
42 44
 							suffix = "_p" + str(n)
43 45
 						else:
44 46
 							suffix = "_w" + str(n)
45 47
 					else:
46 48
 						suffix = ""
47  
-					r.append(("dfi_" + signal[1] + suffix, getattr(phase, signal[1])))
  49
+					r.append(("dfi_" + field + suffix, getattr(phase, field)))
48 50
 		return r
49 51
 
50  
-def interconnect_stmts(master, slave):
51  
-	r = []
52  
-	for pm, ps in zip(master.phases, slave.phases):
53  
-		r += simple_interconnect_stmts(master.pdesc, pm, [ps])
54  
-	return r
55  
-
56  
-class Interconnect:
  52
+class Interconnect(Module):
57 53
 	def __init__(self, master, slave):
58  
-		self.master = master
59  
-		self.slave = slave
60  
-	
61  
-	def get_fragment(self):
62  
-		return Fragment(interconnect_stmts(self.master, self.slave))
  54
+		self.comb += master.connect(slave)
47  migen/bus/simple.py
... ...
@@ -1,47 +0,0 @@
1  
-from migen.fhdl.structure import *
2  
-from migen.genlib.misc import optree
3  
-
4  
-(S_TO_M, M_TO_S) = range(2)
5  
-
6  
-# desc is a list of tuples, each made up of:
7  
-# 0) S_TO_M/M_TO_S: data direction
8  
-# 1) string: name
9  
-# 2) int: width
10  
-
11  
-class Description:
12  
-	def __init__(self, *desc):
13  
-		self.desc = desc
14  
-	
15  
-	def get_names(self, direction, *exclude_list):
16  
-		exclude = set(exclude_list)
17  
-		return [signal[1]
18  
-			for signal in self.desc
19  
-			if signal[0] == direction and signal[1] not in exclude]
20  
-
21  
-class SimpleInterface:
22  
-	def __init__(self, desc):
23  
-		self.desc = desc
24  
-		modules = self.__module__.split(".")
25  
-		busname = modules[len(modules)-1]
26  
-		for signal in self.desc.desc:
27  
-			signame = signal[1]
28  
-			setattr(self, signame, Signal(signal[2], busname + "_" + signame))
29  
-
30  
-def simple_interconnect_stmts(desc, master, slaves):
31  
-	s2m = desc.get_names(S_TO_M)
32  
-	m2s = desc.get_names(M_TO_S)
33  
-	sl = [getattr(slave, name).eq(getattr(master, name))
34  
-		for name in m2s for slave in slaves]
35  
-	sl += [getattr(master, name).eq(
36  
-			optree("|", [getattr(slave, name) for slave in slaves])
37  
-		)
38  
-		for name in s2m]
39  
-	return sl
40  
-
41  
-class SimpleInterconnect:
42  
-	def __init__(self, master, slaves):
43  
-		self.master = master
44  
-		self.slaves = slaves
45  
-	
46  
-	def get_fragment(self):
47  
-		return Fragment(simple_interconnect_stmts(self.master.desc, self.master, self.slaves))
154  migen/bus/wishbone.py
@@ -2,64 +2,59 @@
2 2
 from migen.fhdl.specials import Memory
3 3
 from migen.fhdl.module import Module
4 4
 from migen.genlib import roundrobin
  5
+from migen.genlib.record import *
5 6
 from migen.genlib.misc import optree
6  
-from migen.bus.simple import *
7 7
 from migen.bus.transactions import *
8 8
 from migen.sim.generic import Proxy
9 9
 
10  
-_desc = Description(
11  
-	(M_TO_S,	"adr",		30),
12  
-	(M_TO_S,	"dat_w",	32),
13  
-	(S_TO_M,	"dat_r",	32),
14  
-	(M_TO_S,	"sel",		4),
15  
-	(M_TO_S,	"cyc",		1),
16  
-	(M_TO_S,	"stb",		1),
17  
-	(S_TO_M,	"ack",		1),
18  
-	(M_TO_S,	"we",		1),
19  
-	(M_TO_S,	"cti",		3),
20  
-	(M_TO_S,	"bte",		2),
21  
-	(S_TO_M,	"err",		1)
22  
-)
  10
+_layout = [
  11
+	("adr",		30,		DIR_M_TO_S),
  12
+	("dat_w",	32, 	DIR_M_TO_S),
  13
+	("dat_r",	32, 	DIR_S_TO_M),
  14
+	("sel",		4,		DIR_M_TO_S),
  15
+	("cyc",		1,		DIR_M_TO_S),
  16
+	("stb",		1,		DIR_M_TO_S),
  17
+	("ack",		1,		DIR_S_TO_M),
  18
+	("we",		1,		DIR_M_TO_S),
  19
+	("cti",		3,		DIR_M_TO_S),
  20
+	("bte",		2,		DIR_M_TO_S),
  21
+	("err",		1,		DIR_S_TO_M)
  22
+]
23 23
 
24  
-class Interface(SimpleInterface):
  24
+class Interface(Record):
25 25
 	def __init__(self):
26  
-		SimpleInterface.__init__(self, _desc)
  26
+		Record.__init__(self, _layout)
27 27
 
28  
-class InterconnectPointToPoint(SimpleInterconnect):
  28
+class InterconnectPointToPoint(Module):
29 29
 	def __init__(self, master, slave):
30  
-		SimpleInterconnect.__init__(self, master, [slave])
  30
+		self.comb += master.connect(slave)
31 31
 
32  
-class Arbiter:
  32
+class Arbiter(Module):
33 33
 	def __init__(self, masters, target):
34  
-		self.masters = masters
35  
-		self.target = target
36  
-		self.rr = roundrobin.RoundRobin(len(self.masters))
37  
-
38  
-	def get_fragment(self):
39  
-		comb = []
  34
+		self.submodules.rr = roundrobin.RoundRobin(len(masters))
40 35
 		
41 36
 		# mux master->slave signals
42  
-		for name in _desc.get_names(M_TO_S):
43  
-			choices = Array(getattr(m, name) for m in self.masters)
44  
-			comb.append(getattr(self.target, name).eq(choices[self.rr.grant]))
  37
+		for name, size, direction in _layout:
  38
+			if direction == DIR_M_TO_S:
  39
+				choices = Array(getattr(m, name) for m in masters)
  40
+				self.comb += getattr(target, name).eq(choices[self.rr.grant])
45 41
 		
46 42
 		# connect slave->master signals
47  
-		for name in _desc.get_names(S_TO_M):
48  
-			source = getattr(self.target, name)
49  
-			for i, m in enumerate(self.masters):
50  
-				dest = getattr(m, name)
51  
-				if name == "ack" or name == "err":
52  
-					comb.append(dest.eq(source & (self.rr.grant == i)))
53  
-				else:
54  
-					comb.append(dest.eq(source))
  43
+		for name, size, direction in _layout:
  44
+			if direction == DIR_S_TO_M:
  45
+				source = getattr(target, name)
  46
+				for i, m in enumerate(masters):
  47
+					dest = getattr(m, name)
  48
+					if name == "ack" or name == "err":
  49
+						self.comb += dest.eq(source & (self.rr.grant == i))
  50
+					else:
  51
+						self.comb += dest.eq(source)
55 52
 		
56 53
 		# connect bus requests to round-robin selector
57  
-		reqs = [m.cyc for m in self.masters]
58  
-		comb.append(self.rr.request.eq(Cat(*reqs)))
59  
-		
60  
-		return Fragment(comb) + self.rr.get_fragment()
  54
+		reqs = [m.cyc for m in masters]
  55
+		self.comb += self.rr.request.eq(Cat(*reqs))
61 56
 
62  
-class Decoder:
  57
+class Decoder(Module):
63 58
 	# slaves is a list of pairs:
64 59
 	# 0) function that takes the address signal and returns a FHDL expression
65 60
 	#    that evaluates to 1 when the slave is selected and 0 otherwise.
@@ -67,55 +62,43 @@ class Decoder:
67 62
 	# register adds flip-flops after the address comparators. Improves timing,
68 63
 	# but breaks Wishbone combinatorial feedback.
69 64
 	def __init__(self, master, slaves, register=False):
70  
-		self.master = master
71  
-		self.slaves = slaves
72  
-		self.register = register
73  
-
74  
-	def get_fragment(self):
75  
-		comb = []
76  
-		sync = []
77  
-		
78  
-		ns = len(self.slaves)
  65
+		ns = len(slaves)
79 66
 		slave_sel = Signal(ns)
80 67
 		slave_sel_r = Signal(ns)
81 68
 		
82 69
 		# decode slave addresses
83  
-		comb += [slave_sel[i].eq(fun(self.master.adr))
84  
-			for i, (fun, bus) in enumerate(self.slaves)]
85  
-		if self.register:
86  
-			sync.append(slave_sel_r.eq(slave_sel))
  70
+		self.comb += [slave_sel[i].eq(fun(master.adr))
  71
+			for i, (fun, bus) in enumerate(slaves)]
  72
+		if register:
  73
+			self.sync += slave_sel_r.eq(slave_sel)
87 74
 		else:
88  
-			comb.append(slave_sel_r.eq(slave_sel))
  75
+			self.comb += slave_sel_r.eq(slave_sel)
89 76
 		
90 77
 		# connect master->slaves signals except cyc
91  
-		m2s_names = _desc.get_names(M_TO_S, "cyc")
92  
-		comb += [getattr(slave[1], name).eq(getattr(self.master, name))
93  
-			for name in m2s_names for slave in self.slaves]
  78
+		for slave in slaves:
  79
+			for name, size, direction in _layout:
  80
+				if direction == DIR_M_TO_S and name != "cyc":
  81
+					self.comb += getattr(slave[1], name).eq(getattr(master, name))
94 82
 		
95 83
 		# combine cyc with slave selection signals
96  
-		comb += [slave[1].cyc.eq(self.master.cyc & slave_sel[i])
97  
-			for i, slave in enumerate(self.slaves)]
  84
+		self.comb += [slave[1].cyc.eq(master.cyc & slave_sel[i])
  85
+			for i, slave in enumerate(slaves)]
98 86
 		
99 87
 		# generate master ack (resp. err) by ORing all slave acks (resp. errs)
100  
-		comb += [
101  
-			self.master.ack.eq(optree("|", [slave[1].ack for slave in self.slaves])),
102  
-			self.master.err.eq(optree("|", [slave[1].err for slave in self.slaves]))
  88
+		self.comb += [
  89
+			master.ack.eq(optree("|", [slave[1].ack for slave in slaves])),
  90
+			master.err.eq(optree("|", [slave[1].err for slave in slaves]))
103 91
 		]
104 92
 		
105 93
 		# mux (1-hot) slave data return
106  
-		masked = [Replicate(slave_sel_r[i], len(self.master.dat_r)) & self.slaves[i][1].dat_r for i in range(len(self.slaves))]
107  
-		comb.append(self.master.dat_r.eq(optree("|", masked)))
108  
-		
109  
-		return Fragment(comb, sync)
  94
+		masked = [Replicate(slave_sel_r[i], len(master.dat_r)) & slaves[i][1].dat_r for i in range(ns)]
  95
+		self.comb += master.dat_r.eq(optree("|", masked))
110 96
 
111  
-class InterconnectShared:
  97
+class InterconnectShared(Module):
112 98
 	def __init__(self, masters, slaves, register=False):
113  
-		self._shared = Interface()
114  
-		self._arbiter = Arbiter(masters, self._shared)
115  
-		self._decoder = Decoder(self._shared, slaves, register)
116  
-	
117  
-	def get_fragment(self):
118  
-		return self._arbiter.get_fragment() + self._decoder.get_fragment()
  99
+		shared = Interface()
  100
+		self.submodules += Arbiter(masters, shared)
  101
+		self.submodules += Decoder(shared, slaves, register)
119 102
 
120 103
 class Tap(Module):
121 104
 	def __init__(self, bus, handler=print):
@@ -200,34 +183,33 @@ def do_simulation(self, s):
200 183
 		else:
201 184
 			bus.ack = 0
202 185
 
203  
-class SRAM:
  186
+class SRAM(Module):
204 187
 	def __init__(self, mem_or_size, bus=None):
205 188
 		if isinstance(mem_or_size, Memory):
206 189
 			assert(mem_or_size.width <= 32)
207  
-			self.mem = mem_or_size
  190
+			mem = mem_or_size
208 191
 		else:
209  
-			self.mem = Memory(32, mem_or_size//4)
  192
+			mem = Memory(32, mem_or_size//4)
210 193
 		if bus is None:
211 194
 			bus = Interface()
212 195
 		self.bus = bus
213 196
 	
214  
-	def get_fragment(self):
  197
+		###
  198
+	
215 199
 		# memory
216  
-		port = self.mem.get_port(write_capable=True, we_granularity=8)
  200
+		self.specials += mem
  201
+		port = mem.get_port(write_capable=True, we_granularity=8)
217 202
 		# generate write enable signal
218  
-		comb = [port.we[i].eq(self.bus.cyc & self.bus.stb & self.bus.we & self.bus.sel[i])
  203
+		self.comb += [port.we[i].eq(self.bus.cyc & self.bus.stb & self.bus.we & self.bus.sel[i])
219 204
 			for i in range(4)]
220 205
 		# address and data
221  
-		comb += [
  206
+		self.comb += [
222 207
 			port.adr.eq(self.bus.adr[:len(port.adr)]),
223 208
 			port.dat_w.eq(self.bus.dat_w),
224 209
 			self.bus.dat_r.eq(port.dat_r)
225 210
 		]
226 211
 		# generate ack
227  
-		sync = [
  212
+		self.sync += [
228 213
 			self.bus.ack.eq(0),
229  
-			If(self.bus.cyc & self.bus.stb & ~self.bus.ack,
230  
-				self.bus.ack.eq(1)
231  
-			)
  214
+			If(self.bus.cyc & self.bus.stb & ~self.bus.ack,	self.bus.ack.eq(1))
232 215
 		]
233  
-		return Fragment(comb, sync, specials={self.mem})
11  migen/bus/wishbone2asmi.py
@@ -3,7 +3,7 @@
3 3
 from migen.bus import wishbone
4 4
 from migen.genlib.fsm import FSM
5 5
 from migen.genlib.misc import split, displacer, chooser
6  
-from migen.genlib.record import Record
  6
+from migen.genlib.record import Record, layout_len
7 7
 
8 8
 # cachesize (in 32-bit words) is the size of the data store, must be a power of 2
9 9
 class WB2ASMI:
@@ -60,15 +60,14 @@ def get_fragment(self):
60 60
 		]
61 61
 		
62 62
 		# Tag memory
63  
-		tag_mem = Memory(tagbits+1, 2**linebits)
64  
-		tag_port = tag_mem.get_port(write_capable=True)
65  
-		
66 63
 		tag_layout = [("tag", tagbits), ("dirty", 1)]
  64
+		tag_mem = Memory(layout_len(tag_layout), 2**linebits)
  65
+		tag_port = tag_mem.get_port(write_capable=True)
67 66
 		tag_do = Record(tag_layout)
68 67
 		tag_di = Record(tag_layout)
69 68
 		comb += [
70  
-			Cat(*tag_do.flatten()).eq(tag_port.dat_r),
71  
-			tag_port.dat_w.eq(Cat(*tag_di.flatten()))
  69
+			tag_do.raw_bits().eq(tag_port.dat_r),
  70
+			tag_port.dat_w.eq(tag_di.raw_bits())
72 71
 		]
73 72
 			
74 73
 		comb += [
1  migen/flow/actor.py
@@ -163,7 +163,6 @@ def get_binary_control_fragment(self, stb_i, ack_o, stb_o, ack_i):
163 163
 def get_conn_fragment(source, sink):
164 164
 	assert isinstance(source, Source)
165 165
 	assert isinstance(sink, Sink)
166  
-	assert sink.token.compatible(source.token)
167 166
 	sigs_source = source.token.flatten()
168 167
 	sigs_sink = sink.token.flatten()
169 168
 	comb = [
2  migen/flow/network.py
@@ -170,7 +170,7 @@ def _infer_plumbing_layout(self):
170 170
 						other_ep = other.single_sink()
171 171
 				else:
172 172
 					raise AssertionError
173  
-				layout = other.token(other_ep).layout()
  173
+				layout = other.token(other_ep).layout
174 174
 				a.parameters["layout"] = layout
175 175
 				self.instantiate(a)
176 176
 	
53  migen/flow/plumbing.py
... ...
@@ -1,4 +1,5 @@
1 1
 from migen.fhdl.structure import *
  2
+from migen.fhdl.module import Module
2 3
 from migen.flow.actor import *
3 4
 from migen.genlib.record import *
4 5
 from migen.genlib.misc import optree
@@ -14,57 +15,45 @@ def get_process_fragment(self):
14 15
 		sync = [If(self.pipe_ce, Cat(*sigs_q).eq(Cat(*sigs_d)))]
15 16
 		return Fragment(sync=sync)
16 17
 
17  
-class Combinator(Actor):
  18
+class Combinator(Module, Actor):
18 19
 	def __init__(self, layout, subrecords):
19  
-		source = Record(layout)
20  
-		subrecords = [source.subrecord(*subr) for subr in subrecords]
21  
-		eps = [("sink{0}".format(n), Sink, r)
  20
+		eps = [("source", Source, layout)]
  21
+		eps += [("sink"+str(n), Sink, layout_partial(layout, r))
22 22
 			for n, r in enumerate(subrecords)]
23  
-		ep_source = ("source", Source, source)
24  
-		eps.append(ep_source)
25 23
 		Actor.__init__(self, *eps)
26 24
 
27  
-	def get_fragment(self):
  25
+		###
  26
+	
28 27
 		source = self.endpoints["source"]
29  
-		sinks = [self.endpoints["sink{0}".format(n)]
  28
+		sinks = [self.endpoints["sink"+str(n)]
30 29
 			for n in range(len(self.endpoints)-1)]
31  
-		comb = [source.stb.eq(optree("&", [sink.stb for sink in sinks]))]
32  
-		comb += [sink.ack.eq(source.ack & source.stb) for sink in sinks]
33  
-		return Fragment(comb)
  30
+		self.comb += [source.stb.eq(optree("&", [sink.stb for sink in sinks]))]
  31
+		self.comb += [sink.ack.eq(source.ack & source.stb) for sink in sinks]
  32
+		self.comb += [source.token.eq(sink.token) for sink in sinks]
34 33
 
35  
-class Splitter(Actor):
  34
+class Splitter(Module, Actor):
36 35
 	def __init__(self, layout, subrecords):
37  
-		sink = Record(layout)
38  
-		subr = []
39  
-		for s in subrecords:
40  
-			if s is None:
41  
-				subr.append(sink)
42  
-			else:
43  
-				subr.append(sink.subrecord(*s))
44  
-		eps = [("source{0}".format(n), Source, r)
45  
-			for n, r in enumerate(subr)]
46  
-		ep_sink = ("sink", Sink, sink)
47  
-		eps.append(ep_sink)
  36
+		eps = [("sink", Sink, layout)]
  37
+		eps += [("source"+str(n), Source, layout_partial(layout, *r))
  38
+			for n, r in enumerate(subrecords)]
48 39
 		Actor.__init__(self, *eps)
49 40
 		
50  
-	def get_fragment(self):
  41
+		###
  42
+
51 43
 		sources = [self.endpoints[e] for e in self.sources()]
52 44
 		sink = self.endpoints[self.sinks()[0]]
  45
+
  46
+		self.comb += [source.token.eq(sink.token) for source in sources]
53 47
 		
54 48
 		already_acked = Signal(len(sources))
55  
-		sync = [
56  
-			If(sink.stb,
  49
+		self.sync += If(sink.stb,
57 50
 				already_acked.eq(already_acked | Cat(*[s.ack for s in sources])),
58 51
 				If(sink.ack, already_acked.eq(0))
59 52
 			)
60  
-		]
61  
-		comb = [
62  
-			sink.ack.eq(optree("&",
  53
+		self.comb += sink.ack.eq(optree("&",
63 54
 				[s.ack | already_acked[n] for n, s in enumerate(sources)]))
64  
-		]
65 55
 		for n, s in enumerate(sources):
66  
-			comb.append(s.stb.eq(sink.stb & ~already_acked[n]))
67  
-		return Fragment(comb, sync)
  56
+			self.comb += s.stb.eq(sink.stb & ~already_acked[n])
68 57
 
69 58
 # Actors whose layout should be inferred from what their single sink is connected to.
70 59
 layout_sink = {Buffer, Splitter}
197  migen/genlib/record.py
... ...
@@ -1,112 +1,121 @@
1 1
 from migen.fhdl.structure import *
2  
-from migen.fhdl.tools import value_bits_sign
  2
+from migen.fhdl.tracer import get_obj_var_name
  3
+from migen.genlib.misc import optree
  4
+
  5
+(DIR_NONE, DIR_S_TO_M, DIR_M_TO_S) = range(3)
  6
+
  7
+# Possible layout elements:
  8
+#   1. (name, size)
  9
+#   2. (name, size, direction)
  10
+#   3. (name, sublayout)
  11
+# size can be an int, or a (int, bool) tuple for signed numbers
  12
+# sublayout must be a list
  13
+
  14
+def layout_len(layout):
  15
+	r = 0
  16
+	for f in layout:
  17
+		if isinstance(f[1], (int, tuple)): # cases 1/2
  18
+			if(len(f) == 3):
  19
+				fname, fsize, fdirection = f
  20
+			else:
  21
+				fname, fsize = f
  22
+		elif isinstance(f[1], list): # case 3
  23
+			fname, fsublayout = f
  24
+			fsize = layout_len(fsublayout)
  25
+		else:
  26
+			raise TypeError
  27
+		if isinstance(fsize, tuple):
  28
+			r += fsize[0]
  29
+		else:
  30
+			r += fsize
  31
+	return r
  32
+
  33
+def layout_get(layout, name):
  34
+	for f in layout:
  35
+		if f[0] == name:
  36
+			return f
  37
+	raise KeyError
  38
+
  39
+def layout_partial(layout, *elements):
  40
+	r = []
  41
+	for path in elements:
  42
+		path_s = path.split("/")
  43
+		last = path_s.pop()
  44
+		copy_ref = layout
  45
+		insert_ref = r
  46
+		for hop in path_s:
  47
+			name, copy_ref = layout_get(copy_ref, hop)
  48
+			try:
  49
+				name, insert_ref = layout_get(insert_ref, hop)
  50
+			except KeyError:
  51
+				new_insert_ref = []
  52
+				insert_ref.append((hop, new_insert_ref))
  53
+				insert_ref = new_insert_ref
  54
+		insert_ref.append(layout_get(copy_ref, last))
  55
+	return r
3 56
 
4 57
 class Record:
5  
-	def __init__(self, layout, name=""):
6  
-		self.name = name
7  
-		self.field_order = []
  58
+	def __init__(self, layout, name=None):
  59
+		self.name = get_obj_var_name(name, "")
  60
+		self.layout = layout
  61
+
8 62
 		if self.name:
9 63
 			prefix = self.name + "_"
10 64
 		else:
11 65
 			prefix = ""
12  
-		for f in layout:
13  
-			if isinstance(f, tuple):
14  
-				if isinstance(f[1], (int, tuple)):
15  
-					setattr(self, f[0], Signal(f[1], prefix + f[0]))
16  
-				elif isinstance(f[1], Signal) or isinstance(f[1], Record):
17  
-					setattr(self, f[0], f[1])
18  
-				elif isinstance(f[1], list):
19  
-					setattr(self, f[0], Record(f[1], prefix + f[0]))
20  
-				else:
21  
-					raise TypeError
22  
-				if len(f) == 3:
23  
-					self.field_order.append((f[0], f[2]))
  66
+		for f in self.layout:
  67
+			if isinstance(f[1], (int, tuple)): # cases 1/2
  68
+				if(len(f) == 3):
  69
+					fname, fsize, fdirection = f
24 70
 				else:
25  
-					self.field_order.append((f[0], 1))
  71
+					fname, fsize = f
  72
+				finst = Signal(fsize, name=prefix + fname)
  73
+			elif isinstance(f[1], list): # case 3
  74
+				fname, fsublayout = f
  75
+				finst = Record(fsublayout, prefix + fname)
26 76
 			else:
27  
-				setattr(self, f, Signal(1, prefix + f))
28  
-				self.field_order.append((f, 1))
  77
+				raise TypeError
  78
+			setattr(self, fname, finst)
29 79
 
30 80
 	def eq(self, other):
31  
-		return [getattr(self, key).eq(getattr(other, key))
32  
-		  for key, a in self.field_order]
33  
-
34  
-	def layout(self):
35  
-		l = []
36  
-		for key, alignment in self.field_order:
37  
-			e = getattr(self, key)
38  
-			if isinstance(e, Signal):
39  
-				l.append((key, (e.nbits, e.signed), alignment))
40  
-			elif isinstance(e, Record):
41  
-				l.append((key, e.layout(), alignment))
42  
-		return l
43  
-	
44  
-	def copy(self, name=None):
45  
-		return Record(self.layout(), name)
46  
-	
47  
-	def get_alignment(self, name):
48  
-		return list(filter(lambda x: x[0] == name, self.field_order))[0][1]
49  
-	
50  
-	def subrecord(self, *descr):
51  
-		fields = []
52  
-		for item in descr:
53  
-			path = item.split("/")
54  
-			last = path.pop()
55  
-			pos_self = self
56  
-			pos_fields = fields
57  
-			for hop in path:
58  
-				pos_self = getattr(pos_self, hop)
59  
-				lu = list(filter(lambda x: x[0] == hop, pos_fields))
60  
-				try:
61  
-					pos_fields = lu[0][1]
62  
-				except IndexError:
63  
-					n = []
64  
-					pos_fields.append((hop, n))
65  
-					pos_fields = n
66  
-				if not isinstance(pos_fields, list):
67  
-					raise ValueError
68  
-			if len(list(filter(lambda x: x[0] == last, pos_fields))) > 0:
69  
-				raise ValueError
70  
-			pos_fields.append((last, getattr(pos_self, last), pos_self.get_alignment(last)))
71  
-		return Record(fields, "subrecord")
  81
+		return [getattr(self, f[0]).eq(getattr(other, f[0]))
  82
+		  for f in self.layout if hasattr(other, f[0])]
72 83
 	
73  
-	def compatible(self, other):
74  
-		tpl1 = self.flatten()
75  
-		tpl2 = other.flatten()
76  
-		return len(tpl1) == len(tpl2)
77  
-	
78  
-	def flatten(self, align=False, offset=0, return_offset=False):
79  
-		l = []
80  
-		for key, alignment in self.field_order:
81  
-			if align:
82  
-				pad_size = alignment - (offset % alignment)
83  
-				if pad_size < alignment:
84  
-					l.append(Replicate(0, pad_size))
85  
-					offset += pad_size
86  
-			
87  
-			e = getattr(self, key)
  84
+	def flatten(self):
  85
+		r = []
  86
+		for f in self.layout:			
  87
+			e = getattr(self, f[0])
88 88
 			if isinstance(e, Signal):
89  
-				added = [e]
  89
+				r.append(e)
90 90
 			elif isinstance(e, Record):
91  
-				added = e.flatten(align, offset)
  91
+				r += e.flatten()
92 92
 			else:
93 93
 				raise TypeError
94  
-			for x in added:
95  
-				offset += value_bits_sign(x)[0]
96  
-			l += added
97  
-		if return_offset:
98  
-			return (l, offset)
99  
-		else:
100  
-			return l
101  
-	
102  
-	def to_signal(self, assignment_list, sig_out, align=False):
103  
-		flattened, length = self.flatten(align, return_offset=True)
104  
-		raw = Signal(length)
105  
-		if sig_out:
106  
-			assignment_list.append(raw.eq(Cat(*flattened)))
107  
-		else:
108  
-			assignment_list.append(Cat(*flattened).eq(raw))
109  
-		return raw
  94
+		return r
  95
+
  96
+	def raw_bits(self):
  97
+		return Cat(*self.flatten())
110 98
 	
  99
+	def connect(self, *slaves):
  100
+		r = []
  101
+		for f in self.layout:
  102
+			field = f[0]
  103
+			self_e = getattr(self, field)
  104
+			if isinstance(self_e, Signal):
  105
+				direction = f[2]
  106
+				if direction == DIR_M_TO_S:
  107
+					r += [getattr(slave, field).eq(self_e) for slave in slaves]
  108
+				elif direction == DIR_S_TO_M:
  109
+					r.append(self_e.eq(optree("|", [getattr(slave, field) for slave in slaves])))
  110
+				else:
  111
+					raise TypeError
  112
+			else:
  113
+				for slave in slaves:
  114
+					r += self_e.connect(getattr(slave, field))
  115
+		return r
  116
+
  117
+	def __len__(self):
  118
+		return layout_len(self.layout)
  119
+
111 120
 	def __repr__(self):
112  
-		return "<Record " + repr(self.layout()) + ">"
  121
+		return "<Record " + ":".join(f[0] for f in self.layout) + " at " + hex(id(self)) + ">"

No commit comments for this range

Something went wrong with that request. Please try again.