Skip to content

Commit c49a361

Browse files
committedJul 13, 2017
integration: make Wishbone address decoder generator reusable
1 parent 207a8d6 commit c49a361

File tree

2 files changed

+73
-62
lines changed

2 files changed

+73
-62
lines changed
 

Diff for: ‎misoc/integration/soc_core.py

+4-62
Original file line numberDiff line numberDiff line change
@@ -4,55 +4,12 @@
44

55
from misoc.cores import lm32, mor1kx, tmpu, identifier, timer, uart
66
from misoc.interconnect import wishbone, csr_bus, wishbone2csr
7+
from misoc.integration.wb_slaves import WishboneSlaveManager
78

89

910
__all__ = ["SoCCore", "soc_core_args", "soc_core_argdict"]
1011

1112

12-
def split(bit, addresses):
13-
s0 = []
14-
s1 = []
15-
mask = 1 << bit
16-
for address in addresses:
17-
if address & mask:
18-
s1.append(address)
19-
else:
20-
s0.append(address)
21-
return s0, s1
22-
23-
24-
# returns a dict of address -> (bits to test for 0, bits to test for 1)
25-
def make_decoder(word_size, addresses):
26-
if len(addresses) == 1:
27-
return {addresses[0]: ([], [])}
28-
else:
29-
for i in reversed(range(word_size)):
30-
s0, s1 = split(i, addresses)
31-
if s0 and s1:
32-
break
33-
assert s0 and s1
34-
d0 = make_decoder(i, s0)
35-
d1 = make_decoder(i, s1)
36-
r = {}
37-
for address, (bits0, bits1) in d0.items():
38-
r[address] = (bits0 + [i], bits1)
39-
for address, (bits0, bits1) in d1.items():
40-
r[address] = (bits0, bits1 + [i])
41-
return r
42-
43-
44-
def make_sel_fun(bits):
45-
bits0, bits1 = bits
46-
def sel_fun(x):
47-
r = 1
48-
for bit0 in bits0:
49-
r = r & ~x[bit0]
50-
for bit1 in bits1:
51-
r = r & x[bit1]
52-
return r
53-
return sel_fun
54-
55-
5613
class SoCCore(Module):
5714
mem_map = {
5815
"rom": 0x00000000,
@@ -95,7 +52,7 @@ def __init__(self, platform, clk_freq,
9552
self._constants = [] # list of (name, value)
9653

9754
self._wb_masters = []
98-
self._wb_slaves = [] # list of (origin, length, interface)
55+
self._wb_slaves = WishboneSlaveManager(self.shadow_base)
9956

10057
self.config = dict()
10158

@@ -161,18 +118,7 @@ def add_wb_master(self, wbm):
161118
def add_wb_slave(self, origin, length, interface):
162119
if self.finalized:
163120
raise FinalizeError
164-
if origin < 0 or length <= 0 or origin + length > self.shadow_base:
165-
raise ValueError("Invalid range for origin/length of Wishbone region")
166-
if origin & 3 or length & 3:
167-
raise ValueError("Misaligned Wishbone address")
168-
def in_this_region(addr):
169-
return addr >= origin and addr < origin + length
170-
for o, l, _ in self._wb_slaves:
171-
if in_this_region(o) or in_this_region(o+l-1):
172-
raise ValueError("Wishbone conflict with region at 0x{:08x} of length 0x{:x}"
173-
.format(o, l))
174-
175-
self._wb_slaves.append((origin, length, interface))
121+
self._wb_slaves.add(origin, length, interface)
176122

177123
# This function simply registers the memory region for firmware purposes
178124
# (linker script, generated headers)
@@ -229,12 +175,8 @@ def do_finalize(self):
229175
raise FinalizeError("CPU needs a {} to be registered with register_mem()".format(mem))
230176

231177
# Wishbone
232-
decoder = make_decoder(30, [origin >> 2 for origin, _, _ in self._wb_slaves])
233-
wb_slaves = []
234-
for origin, _, interface in self._wb_slaves:
235-
wb_slaves.append((make_sel_fun(decoder[origin >> 2]), interface))
236178
self.submodules.wishbonecon = wishbone.InterconnectShared(self._wb_masters,
237-
wb_slaves, register=True)
179+
self._wb_slaves.get_interconnect_slaves(), register=True)
238180

239181
# CSR
240182
self.submodules.csrbankarray = csr_bus.CSRBankArray(self,

Diff for: ‎misoc/integration/wb_slaves.py

+69
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
def split(bit, addresses):
2+
s0 = []
3+
s1 = []
4+
mask = 1 << bit
5+
for address in addresses:
6+
if address & mask:
7+
s1.append(address)
8+
else:
9+
s0.append(address)
10+
return s0, s1
11+
12+
13+
# returns a dict of address -> (bits to test for 0, bits to test for 1)
14+
def make_decoder(word_size, addresses):
15+
if len(addresses) == 1:
16+
return {addresses[0]: ([], [])}
17+
else:
18+
for i in reversed(range(word_size)):
19+
s0, s1 = split(i, addresses)
20+
if s0 and s1:
21+
break
22+
assert s0 and s1
23+
d0 = make_decoder(i, s0)
24+
d1 = make_decoder(i, s1)
25+
r = {}
26+
for address, (bits0, bits1) in d0.items():
27+
r[address] = (bits0 + [i], bits1)
28+
for address, (bits0, bits1) in d1.items():
29+
r[address] = (bits0, bits1 + [i])
30+
return r
31+
32+
33+
def make_sel_fun(bits):
34+
bits0, bits1 = bits
35+
def sel_fun(x):
36+
r = 1
37+
for bit0 in bits0:
38+
r = r & ~x[bit0]
39+
for bit1 in bits1:
40+
r = r & x[bit1]
41+
return r
42+
return sel_fun
43+
44+
45+
class WishboneSlaveManager:
46+
def __init__(self, max_address):
47+
self.max_address = max_address
48+
self.slaves = [] # list of (origin, length, interface)
49+
50+
def add(self, origin, length, interface):
51+
if origin < 0 or length <= 0 or origin + length > self.max_address:
52+
raise ValueError("Invalid range for origin/length of Wishbone region")
53+
if origin & 3 or length & 3:
54+
raise ValueError("Misaligned Wishbone address")
55+
def in_this_region(addr):
56+
return addr >= origin and addr < origin + length
57+
for o, l, _ in self.slaves:
58+
if in_this_region(o) or in_this_region(o+l-1):
59+
raise ValueError("Wishbone conflict with region at 0x{:08x} of length 0x{:x}"
60+
.format(o, l))
61+
62+
self.slaves.append((origin, length, interface))
63+
64+
def get_interconnect_slaves(self):
65+
decoder = make_decoder(30, [origin >> 2 for origin, _, _ in self.slaves])
66+
ic_slaves = []
67+
for origin, _, interface in self.slaves:
68+
ic_slaves.append((make_sel_fun(decoder[origin >> 2]), interface))
69+
return ic_slaves

0 commit comments

Comments
 (0)
Please sign in to comment.