blob: 7264b54bfcac5c5b41234cea6af4a073269397f3 [file] [log] [blame]
Eunchan Kimc7452942019-12-19 17:04:37 -08001# Copyright lowRISC contributors.
2# Licensed under the Apache License, Version 2.0, see LICENSE for details.
3# SPDX-License-Identifier: Apache-2.0
4
Eunchan Kimc7452942019-12-19 17:04:37 -08005import logging as log
6
7
8def is_pow2(v):
9 """Return true if value is power of two
10 """
11 if not isinstance(v, int):
12 log.warning("is_pow2 received non-integer value {}".format(v))
13 return False
14 t = 1
15 while t <= v:
16 if t == v:
17 return True
18 t = t * 2
19
20 return False
Eunchan Kimeeea1f42020-01-13 10:26:10 -080021
22
23def simplify_addr(dev, xbar):
24 """Make smaller entries by combining them
25
26 If any contiguous regions exist, concatenate them.
27 For instance, 0x1000 ~ 0x1FFF , 0x2000~ 0x2FFF ==> 0x1000 ~ 0x2FFF
28
29 It also checks if there's no device between the gap, then merge
30 the ranges. For instance:
31
32 {0x4000_0000, 0x1_0000}, {0x4008_0000, 0x1_0000} then it combines two
33 entries into {0x4000_0000, 0x9_0000}
34
35 @param addrs List of Dict[Addr] : {'base_addr':,'size_byte':}
36 """
37
38 addrs = dev["addr_range"]
39 # Sort based on the base addr
40 newlist = sorted(addrs, key=lambda k: int(k['base_addr'], 0))
41 # check if overlap or contiguous
42 result = []
43 for e in newlist:
44 if len(result) == 0:
45 result.append(e)
46 continue
47 # if contiguous
48 if int(e["base_addr"], 0) == int(result[-1]["base_addr"], 0) + int(
49 result[-1]["size_byte"], 0):
50 # update previous entry size
51 result[-1]["size_byte"] = "0x{:x}".format(
52 int(result[-1]["size_byte"], 0) + int(e["size_byte"], 0))
53 continue
54
55 if no_device_in_range(xbar, dev["name"], result[-1], e):
56 # Determine if size can be power of 2 value
57 smallest_addr_gte = get_next_base_addr(e["base_addr"], xbar,
58 dev["name"])
59
60 # Choose next value
61 if smallest_addr_gte == -1:
62 next_value = 0x100000000
63 else:
64 next_value = int(smallest_addr_gte["base_addr"], 0)
65
66 calc_size = int(e["base_addr"], 0) + int(e["size_byte"], 0) - int(
67 result[-1]["base_addr"], 0)
68
69 # find power of 2 if possible
70 size_byte = find_pow2_size(result[-1], calc_size, next_value)
71
72 result[-1]["size_byte"] = "0x{:x}".format(size_byte)
73 continue
74
75 # If overlapping (Should it be consider? TlGen will catch it)
76
77 # Normal case
78 result.append(e)
79
80 # return result
81 return result
82
83
84def no_device_in_range(xbar, name, f, t):
85 """Check if other devices doesn't overlap with the range 'from <= x < to'
86 """
87 from_addr = int(f["base_addr"], 0) + int(f["size_byte"], 0)
88 to_addr = int(t["base_addr"], 0)
89
90 for node in [
91 x for x in xbar["nodes"]
92 if x["type"] == "device" and not x["name"] == name
93 ]:
Eunchan Kim837c7962020-04-30 12:15:49 -070094 if "addr_range" not in node:
Eunchan Kimeeea1f42020-01-13 10:26:10 -080095 # Xbar?
96 log.info("Xbar type node cannot be compared in this version.",
97 "Please use in caution")
98 continue
99 assert isinstance(node["addr_range"], list)
100
101 for addr in node["addr_range"]:
102 b_addr = int(addr["base_addr"], 0)
103 e_addr = b_addr + int(addr["size_byte"], 0)
104
105 if e_addr <= from_addr or b_addr >= to_addr:
106 # No overlap
107 continue
108 return False
109 return True
110
111
112def get_next_base_addr(addr, xbar, name):
113 """Return the least value of base_addr of the IP greater than addr
114
115 """
116 if isinstance(addr, str):
117 value = int(addr, 0)
118 else:
119 assert isinstance(addr, int)
120 value = addr
121
122 device_list = [
123 x for x in xbar["nodes"]
124 if x["type"] == "device" and not x["name"] == name
125 ]
126
127 try:
128 addrs = [a for r in device_list for a in r["addr_range"]]
129 except KeyError:
130 log.error("Address range is wrong.\n {}".format(
Eunchan Kim837c7962020-04-30 12:15:49 -0700131 [x for x in device_list if "addr_range" not in x]))
Eunchan Kimeeea1f42020-01-13 10:26:10 -0800132 raise SystemExit()
133
134 sorted_list = sorted(addrs, key=lambda k: int(k["base_addr"], 0))
135
136 gte_list = [x for x in sorted_list if int(x["base_addr"], 0) > value]
137
138 if len(gte_list) == 0:
139 return -1
140
141 return gte_list[0]
142
143
144def find_pow2_size(addr, min_size, next_value):
145 """Find smallest power of 2 value greater than min_size by given addr.
146
147 For instance, {addr:0x4000_0000, min_size:0x21000} and `next_value` as
148 0x40080000, the result will be 0x4_0000
149
150 But it should return result not exceeding the base_addr's leading one bit
151 position. For instance, if the base_addr is 0x4003_0000, the return value
152 should be less than or equal to 0x1_0000. Cannot be 0x4_0000. So, this
153 case, the function returns the original min_size value 0x21000.
154 """
155 base_addr = int(addr["base_addr"], 0)
156
157 diff = next_value - base_addr
158
159 # Find the least one bit position.
160 # If base_addr is 0, then any value can be used
161 if not base_addr == 0:
162 leading_one = 1
163 while True:
164 if base_addr & leading_one != 0:
165 break
166 leading_one = leading_one << 1
167
168 if leading_one <= diff:
169 diff = leading_one
170
171 i = 1
172 while True:
173 i = i << 1
174 if i >= min_size:
175 break
176
177 # If found pow2 value is greater than diff, it cannot be used. Just use
178 # min_size then the tool will use comparators (>=, <=)
179 if i > diff:
180 i = min_size
181
182 # Shall be greater than 4kB
183 assert i >= 0x1000
184
185 return i
Weicai Yang3a2d0bc2021-08-25 15:41:41 -0700186
187
188def get_toggle_excl_bits(addr_ranges, addr_width=32):
189 """ Input addr_ranges is a list of (start_addr, end_addr)
190 From given addr_ranges, will calculate what address bits can't be toggled as
191 only the address in the ranges can pass through the xbar to the device
192 """
193 excl_bits = [] # list of (start_bit, end_bit)
194
195 # Find all the bits that can be toggled to 1
196 toggle_bits = 0
197 for addr in addr_ranges:
198 # The size of the addres range should be power of 2
199 assert is_power_of_two(addr[1] - addr[0] + 1)
200
201 toggle_bits |= addr[0]
202 toggle_bits |= addr[1] - addr[0]
203
204 # Assume toggle_bits = 010011, generate below as bit 2, 3, 5 are never toggled
205 # excl_bits = [(5,5), (2,3)]
206 start_bit = -1
207 for i in range(addr_width):
208 bit = toggle_bits & 1
209 if not bit and start_bit == -1:
210 start_bit = i
211 elif bit and start_bit != -1:
212 excl_bits.append((start_bit, i - 1))
213 start_bit = -1
214
215 toggle_bits = toggle_bits >> 1
216
217 # Handle tailing zero, which are also never toggled
218 if start_bit != -1:
219 excl_bits.append((start_bit, addr_width - 1))
220
221 return excl_bits
222
223
224def is_power_of_two(x):
225 """Function to check if x is power of 2
226 """
227 return (x and (not (x & (x - 1))))