1%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2% Copyright (c) 2009, 2011, ETH Zurich.
3% All rights reserved.
4%
5% This file is distributed under the terms in the attached LICENSE file.
6% If you do not find this file, copies can be found by writing to:
7% ETH Zurich D-INFK, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group.
8%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9
10:-lib(ic).
11:-lib(ic_global).
12:-use_module(library(ic_edge_finder)).
13
14:-dynamic(currentbar/5).
15
16bridge_programming(Plan, NrElements) :-
17    get_devices(Devices),
18    convert_devices(Devices,DeviceElements),
19    get_bridges(Bridges),
20    convert_bridges(Bridges,BridgeElements),
21    append(DeviceElements, BridgeElements, Plan),
22    length(Plan, NrElements).
23
24% note: device with addr(-1,-1,-1) will be removed because it has no
25%       regions -> nuet. The clean way would be to really remove it which leads
26%       to other prolog problems... (two solutions).
27convert_devices([], []).
28convert_devices([buselement(device, Addr ,Regions)|T], L) :-
29    subtract(Regions,[nuet],RegionsClean),
30    ( foreach(R,RegionsClean),
31      foreach(El,Elements),
32      param(Addr)
33      do
34          region(BAR,Base,Bits,Prefetch,Sz,MulL) = R,
35          ( MulL = b ->
36              Mul is 1
37          ;
38            MulL = k ->
39              Mul is 1024
40          ;
41            MulL = g ->
42              Mul is 1024 * 1024 * 1024
43          ;
44              Mul is 1024 * 1024
45          ),
46          Size is Sz * Mul,
47          High is Base + Size,
48          El = buselement(device, Addr, BAR, Base, High, Size, mem, Prefetch, pcie, Bits),
49          assert(bar(Addr,BAR,_,Size,_,_,_))
50    ),
51    convert_devices(T, L2),
52    append(L2, Elements, L).
53
54convert_bridges([], []).
55convert_bridges([buselement(bridge, _, _)|T], L) :-
56    convert_bridges(T, L).
57convert_bridges([buselement(bridge, Addr, S, m(B1,H1), p(B2, H2),_)|T], L) :-
58    ( H1 >= B1 ->
59        S1 is H1 - B1,
60        Bridge1 = [buselement(bridge, Addr, S, B1, H1+1, S1+1, mem, nonprefetchable, pcie, 0)];
61        Bridge1 = []
62    ),
63    ( H2 >= B2 ->
64        S2 is H2 - B2,
65        Bridge2 = [buselement(bridge, Addr, S, B2, H2+1, S2+1, mem, prefetchable, pcie, 0)];
66        Bridge2 = []
67    ),
68    append(Bridge1,Bridge2,BridgeList),
69    convert_bridges(T, L2),
70    append(L2, BridgeList, L).
71
72
73
74%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
75% tools
76%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
77
78
79base(buselement(_,_,_,Base,_,_,_,_,_,_),Base).
80high(buselement(_,_,_,_,High,_,_,_,_,_),High).
81size(buselement(_,_,_,_,_,Size,_,_,_,_),Size).
82
83get_devices(Devices) :-
84    Devices = [buselement(device, addr(-1,-1,-1),[
85    nuet]),
86    buselement(device, addr(16'00,16'00,16'0),[
87    nuet]),
88    buselement(device, addr(16'00,16'01,16'0),[
89    nuet]),
90    buselement(device, addr(16'00,16'01,16'1),[
91    nuet]),
92    buselement(device, addr(16'00,16'02,16'0),[
93    nuet]),
94    buselement(device, addr(16'00,16'02,16'2),[
95    nuet]),
96    buselement(device, addr(16'00,16'03,16'0),[
97    nuet]),
98    buselement(device, addr(16'00,16'04,16'0),[
99	    region(0,16'3803fff90000,64,nonprefetchable,16,k),
100    nuet]),
101    buselement(device, addr(16'00,16'04,16'1),[
102	    region(0,16'3803fff80000,64,nonprefetchable,16,k),
103    nuet]),
104    buselement(device, addr(16'00,16'04,16'2),[
105	    region(0,16'3803fff70000,64,nonprefetchable,16,k),
106    nuet]),
107    buselement(device, addr(16'00,16'04,16'3),[
108	    region(0,16'3803fff60000,64,nonprefetchable,16,k),
109    nuet]),
110    buselement(device, addr(16'00,16'04,16'4),[
111	    region(0,16'3803fff50000,64,nonprefetchable,16,k),
112    nuet]),
113    buselement(device, addr(16'00,16'04,16'5),[
114	    region(0,16'3803fff40000,64,nonprefetchable,16,k),
115    nuet]),
116    buselement(device, addr(16'00,16'04,16'6),[
117	    region(0,16'3803fff30000,64,nonprefetchable,16,k),
118    nuet]),
119    buselement(device, addr(16'00,16'04,16'7),[
120	    region(0,16'3803fff20000,64,nonprefetchable,16,k),
121    nuet]),
122    buselement(device, addr(16'00,16'05,16'0),[
123    nuet]),
124    buselement(device, addr(16'00,16'05,16'1),[
125    nuet]),
126    buselement(device, addr(16'00,16'05,16'2),[
127    nuet]),
128    buselement(device, addr(16'00,16'05,16'4),[
129	    region(0,16'd0f60000,32,nonprefetchable,4,k),
130    nuet]),
131    buselement(device, addr(16'00,16'11,16'0),[
132    nuet]),
133    buselement(device, addr(16'00,16'16,16'0),[
134	    region(0,16'd0f50000,64,nonprefetchable,16,b),
135    nuet]),
136    buselement(device, addr(16'00,16'16,16'1),[
137	    region(0,16'd0f40000,64,nonprefetchable,16,b),
138    nuet]),
139    buselement(device, addr(16'00,16'1a,16'0),[
140	    region(0,16'd0f20000,32,nonprefetchable,1,k),
141    nuet]),
142    buselement(device, addr(16'00,16'1c,16'0),[
143    nuet]),
144    buselement(device, addr(16'00,16'1c,16'7),[
145    nuet]),
146    buselement(device, addr(16'00,16'1d,16'0),[
147	    region(0,16'd0f10000,32,nonprefetchable,1,k),
148    nuet]),
149    buselement(device, addr(16'00,16'1e,16'0),[
150    nuet]),
151    buselement(device, addr(16'00,16'1f,16'0),[
152    nuet]),
153    buselement(device, addr(16'00,16'1f,16'2),[
154	    region(5,16'd0f00000,32,nonprefetchable,2,k),
155    nuet]),
156    buselement(device, addr(16'00,16'1f,16'3),[
157	    region(0,16'3803fff10000,64,nonprefetchable,256,b),
158    nuet]),
159    buselement(device, addr(16'02,16'00,16'0),[
160	    region(0,16'd0960000,32,nonprefetchable,128,k),
161	    region(3,16'd09b0000,32,nonprefetchable,16,k),
162    nuet]),
163    buselement(device, addr(16'02,16'00,16'1),[
164	    region(0,16'd0940000,32,nonprefetchable,128,k),
165	    region(3,16'd09a0000,32,nonprefetchable,16,k),
166    nuet]),
167    buselement(device, addr(16'02,16'00,16'2),[
168	    region(0,16'd0920000,32,nonprefetchable,128,k),
169	    region(3,16'd0990000,32,nonprefetchable,16,k),
170    nuet]),
171    buselement(device, addr(16'02,16'00,16'3),[
172	    region(0,16'd0900000,32,nonprefetchable,128,k),
173	    region(3,16'd0980000,32,nonprefetchable,16,k),
174    nuet]),
175    buselement(device, addr(16'04,16'00,16'0),[
176	    region(0,16'd0e20000,64,nonprefetchable,128,k),
177	    region(4,16'd0e50000,64,nonprefetchable,16,k),
178    nuet]),
179    buselement(device, addr(16'04,16'00,16'1),[
180	    region(0,16'd0e00000,64,nonprefetchable,128,k),
181	    region(4,16'd0e40000,64,nonprefetchable,16,k),
182    nuet]),
183    buselement(device, addr(16'06,16'00,16'0),[
184	    region(1,16'd0d60000,64,nonprefetchable,16,k),
185	    region(3,16'd0d00000,64,nonprefetchable,256,k),
186    nuet]),
187    buselement(device, addr(16'07,16'00,16'0),[
188	    region(0,16'380000000000,64,prefetchable,8,g),
189	    region(4,16'd0c00000,64,nonprefetchable,128,k),
190    nuet]),
191    buselement(device, addr(16'08,16'00,16'0),[
192	    region(0,16'380200400000,64,prefetchable,16,k),
193	    region(2,16'380200000000,64,prefetchable,4,m),
194    nuet]),
195    buselement(device, addr(16'08,16'00,16'3),[
196	    region(0,16'd0b00000,32,nonprefetchable,4,k),
197    nuet]),
198    buselement(device, addr(16'0a,16'00,16'0),[
199	    region(0,16'ea000000,32,prefetchable,16,m),
200	    region(1,16'd0810000,32,nonprefetchable,16,k),
201	    region(2,16'd0000000,32,nonprefetchable,8,m),
202    nuet]),
203    buselement(device, addr(16'7f,16'08,16'0),[
204    nuet]),
205    buselement(device, addr(16'7f,16'09,16'0),[
206    nuet]),
207    buselement(device, addr(16'7f,16'0a,16'0),[
208    nuet]),
209    buselement(device, addr(16'7f,16'0a,16'1),[
210    nuet]),
211    buselement(device, addr(16'7f,16'0a,16'2),[
212    nuet]),
213    buselement(device, addr(16'7f,16'0a,16'3),[
214    nuet]),
215    buselement(device, addr(16'7f,16'0b,16'0),[
216    nuet]),
217    buselement(device, addr(16'7f,16'0b,16'3),[
218    nuet]),
219    buselement(device, addr(16'7f,16'0c,16'0),[
220    nuet]),
221    buselement(device, addr(16'7f,16'0c,16'1),[
222    nuet]),
223    buselement(device, addr(16'7f,16'0c,16'2),[
224    nuet]),
225    buselement(device, addr(16'7f,16'0c,16'3),[
226    nuet]),
227    buselement(device, addr(16'7f,16'0c,16'4),[
228    nuet]),
229    buselement(device, addr(16'7f,16'0d,16'0),[
230    nuet]),
231    buselement(device, addr(16'7f,16'0d,16'1),[
232    nuet]),
233    buselement(device, addr(16'7f,16'0d,16'2),[
234    nuet]),
235    buselement(device, addr(16'7f,16'0d,16'3),[
236    nuet]),
237    buselement(device, addr(16'7f,16'0d,16'4),[
238    nuet]),
239    buselement(device, addr(16'7f,16'0e,16'0),[
240    nuet]),
241    buselement(device, addr(16'7f,16'0e,16'1),[
242    nuet]),
243    buselement(device, addr(16'7f,16'0f,16'0),[
244    nuet]),
245    buselement(device, addr(16'7f,16'0f,16'1),[
246    nuet]),
247    buselement(device, addr(16'7f,16'0f,16'2),[
248    nuet]),
249    buselement(device, addr(16'7f,16'0f,16'3),[
250    nuet]),
251    buselement(device, addr(16'7f,16'0f,16'4),[
252    nuet]),
253    buselement(device, addr(16'7f,16'0f,16'5),[
254    nuet]),
255    buselement(device, addr(16'7f,16'10,16'0),[
256    nuet]),
257    buselement(device, addr(16'7f,16'10,16'1),[
258    nuet]),
259    buselement(device, addr(16'7f,16'10,16'2),[
260    nuet]),
261    buselement(device, addr(16'7f,16'10,16'3),[
262    nuet]),
263    buselement(device, addr(16'7f,16'10,16'4),[
264    nuet]),
265    buselement(device, addr(16'7f,16'10,16'5),[
266    nuet]),
267    buselement(device, addr(16'7f,16'10,16'6),[
268    nuet]),
269    buselement(device, addr(16'7f,16'10,16'7),[
270    nuet]),
271    buselement(device, addr(16'7f,16'13,16'0),[
272    nuet]),
273    buselement(device, addr(16'7f,16'13,16'1),[
274    nuet]),
275    buselement(device, addr(16'7f,16'13,16'4),[
276    nuet]),
277    buselement(device, addr(16'7f,16'13,16'5),[
278    nuet]),
279    buselement(device, addr(16'7f,16'13,16'6),[
280    nuet]),
281    buselement(device, addr(16'7f,16'16,16'0),[
282    nuet]),
283    buselement(device, addr(16'7f,16'16,16'1),[
284    nuet]),
285    buselement(device, addr(16'7f,16'16,16'2),[
286    nuet]),
287    buselement(device, addr(16'80,16'01,16'0),[
288    nuet]),
289    buselement(device, addr(16'80,16'02,16'0),[
290    nuet]),
291    buselement(device, addr(16'80,16'03,16'0),[
292    nuet]),
293    buselement(device, addr(16'80,16'03,16'2),[
294    nuet]),
295    buselement(device, addr(16'80,16'04,16'0),[
296	    region(0,16'3805fff70000,64,nonprefetchable,16,k),
297    nuet]),
298    buselement(device, addr(16'80,16'04,16'1),[
299	    region(0,16'3805fff60000,64,nonprefetchable,16,k),
300    nuet]),
301    buselement(device, addr(16'80,16'04,16'2),[
302	    region(0,16'3805fff50000,64,nonprefetchable,16,k),
303    nuet]),
304    buselement(device, addr(16'80,16'04,16'3),[
305	    region(0,16'3805fff40000,64,nonprefetchable,16,k),
306    nuet]),
307    buselement(device, addr(16'80,16'04,16'4),[
308	    region(0,16'3805fff30000,64,nonprefetchable,16,k),
309    nuet]),
310    buselement(device, addr(16'80,16'04,16'5),[
311	    region(0,16'3805fff20000,64,nonprefetchable,16,k),
312    nuet]),
313    buselement(device, addr(16'80,16'04,16'6),[
314	    region(0,16'3805fff10000,64,nonprefetchable,16,k),
315    nuet]),
316    buselement(device, addr(16'80,16'04,16'7),[
317	    region(0,16'3805fff00000,64,nonprefetchable,16,k),
318    nuet]),
319    buselement(device, addr(16'80,16'05,16'0),[
320    nuet]),
321    buselement(device, addr(16'80,16'05,16'1),[
322    nuet]),
323    buselement(device, addr(16'80,16'05,16'2),[
324    nuet]),
325    buselement(device, addr(16'80,16'05,16'4),[
326	    region(0,16'ec100000,32,nonprefetchable,4,k),
327    nuet]),
328    buselement(device, addr(16'82,16'00,16'0),[
329	    region(0,16'380600000000,64,prefetchable,8,g),
330	    region(4,16'ec000000,64,nonprefetchable,128,k),
331    nuet])].
332
333get_bridges(Bridges) :-
334    Bridges = [buselement(bridge, addr(-1,-1,-1),
335    _),
336    buselement(bridge, addr(16'00,16'00,16'0),
337    _),
338    buselement(bridge, addr(16'00,16'01,16'0),
339    secondary(16'01),
340    m(16'fff00000,16'000fffff),
341    p(16'00000000fff00000,16'00000000000fffff),
342    _),
343    buselement(bridge, addr(16'00,16'01,16'1),
344    secondary(16'02),
345    m(16'd0900000,16'd0afffff),
346    p(16'00000000fff00000,16'00000000000fffff),
347    _),
348    buselement(bridge, addr(16'00,16'02,16'0),
349    secondary(16'04),
350    m(16'd0e00000,16'd0efffff),
351    p(16'0000380200600000,16'00003802009fffff),
352    _),
353    buselement(bridge, addr(16'00,16'02,16'2),
354    secondary(16'06),
355    m(16'd0d00000,16'd0dfffff),
356    p(16'00000000fff00000,16'00000000000fffff),
357    _),
358    buselement(bridge, addr(16'00,16'03,16'0),
359    secondary(16'07),
360    m(16'd0c00000,16'd0cfffff),
361    p(16'0000380000000000,16'00003801ffffffff),
362    _),
363    buselement(bridge, addr(16'00,16'04,16'0),
364    _),
365    buselement(bridge, addr(16'00,16'04,16'1),
366    _),
367    buselement(bridge, addr(16'00,16'04,16'2),
368    _),
369    buselement(bridge, addr(16'00,16'04,16'3),
370    _),
371    buselement(bridge, addr(16'00,16'04,16'4),
372    _),
373    buselement(bridge, addr(16'00,16'04,16'5),
374    _),
375    buselement(bridge, addr(16'00,16'04,16'6),
376    _),
377    buselement(bridge, addr(16'00,16'04,16'7),
378    _),
379    buselement(bridge, addr(16'00,16'05,16'0),
380    _),
381    buselement(bridge, addr(16'00,16'05,16'1),
382    _),
383    buselement(bridge, addr(16'00,16'05,16'2),
384    _),
385    buselement(bridge, addr(16'00,16'05,16'4),
386    _),
387    buselement(bridge, addr(16'00,16'11,16'0),
388    secondary(16'08),
389    m(16'd0b00000,16'd0bfffff),
390    p(16'0000380200000000,16'00003802004fffff),
391    _),
392    buselement(bridge, addr(16'00,16'16,16'0),
393    _),
394    buselement(bridge, addr(16'00,16'16,16'1),
395    _),
396    buselement(bridge, addr(16'00,16'1a,16'0),
397    _),
398    buselement(bridge, addr(16'00,16'1c,16'0),
399    secondary(16'09),
400    m(16'fff00000,16'000fffff),
401    p(16'00000000fff00000,16'00000000000fffff),
402    _),
403    buselement(bridge, addr(16'00,16'1c,16'7),
404    secondary(16'0a),
405    m(16'd0000000,16'd08fffff),
406    p(16'00000000ea000000,16'00000000eaffffff),
407    _),
408    buselement(bridge, addr(16'00,16'1d,16'0),
409    _),
410    buselement(bridge, addr(16'00,16'1e,16'0),
411    secondary(16'0b),
412    m(16'fff00000,16'000fffff),
413    p(16'00000000fff00000,16'00000000000fffff),
414    _),
415    buselement(bridge, addr(16'00,16'1f,16'0),
416    _),
417    buselement(bridge, addr(16'00,16'1f,16'2),
418    _),
419    buselement(bridge, addr(16'00,16'1f,16'3),
420    _),
421    buselement(bridge, addr(16'02,16'00,16'0),
422    _),
423    buselement(bridge, addr(16'02,16'00,16'1),
424    _),
425    buselement(bridge, addr(16'02,16'00,16'2),
426    _),
427    buselement(bridge, addr(16'02,16'00,16'3),
428    _),
429    buselement(bridge, addr(16'04,16'00,16'0),
430    _),
431    buselement(bridge, addr(16'04,16'00,16'1),
432    _),
433    buselement(bridge, addr(16'06,16'00,16'0),
434    _),
435    buselement(bridge, addr(16'07,16'00,16'0),
436    _),
437    buselement(bridge, addr(16'08,16'00,16'0),
438    _),
439    buselement(bridge, addr(16'08,16'00,16'3),
440    _),
441    buselement(bridge, addr(16'0a,16'00,16'0),
442    _),
443    buselement(bridge, addr(16'7f,16'08,16'0),
444    _),
445    buselement(bridge, addr(16'7f,16'09,16'0),
446    _),
447    buselement(bridge, addr(16'7f,16'0a,16'0),
448    _),
449    buselement(bridge, addr(16'7f,16'0a,16'1),
450    _),
451    buselement(bridge, addr(16'7f,16'0a,16'2),
452    _),
453    buselement(bridge, addr(16'7f,16'0a,16'3),
454    _),
455    buselement(bridge, addr(16'7f,16'0b,16'0),
456    _),
457    buselement(bridge, addr(16'7f,16'0b,16'3),
458    _),
459    buselement(bridge, addr(16'7f,16'0c,16'0),
460    _),
461    buselement(bridge, addr(16'7f,16'0c,16'1),
462    _),
463    buselement(bridge, addr(16'7f,16'0c,16'2),
464    _),
465    buselement(bridge, addr(16'7f,16'0c,16'3),
466    _),
467    buselement(bridge, addr(16'7f,16'0c,16'4),
468    _),
469    buselement(bridge, addr(16'7f,16'0d,16'0),
470    _),
471    buselement(bridge, addr(16'7f,16'0d,16'1),
472    _),
473    buselement(bridge, addr(16'7f,16'0d,16'2),
474    _),
475    buselement(bridge, addr(16'7f,16'0d,16'3),
476    _),
477    buselement(bridge, addr(16'7f,16'0d,16'4),
478    _),
479    buselement(bridge, addr(16'7f,16'0e,16'0),
480    _),
481    buselement(bridge, addr(16'7f,16'0e,16'1),
482    _),
483    buselement(bridge, addr(16'7f,16'0f,16'0),
484    _),
485    buselement(bridge, addr(16'7f,16'0f,16'1),
486    _),
487    buselement(bridge, addr(16'7f,16'0f,16'2),
488    _),
489    buselement(bridge, addr(16'7f,16'0f,16'3),
490    _),
491    buselement(bridge, addr(16'7f,16'0f,16'4),
492    _),
493    buselement(bridge, addr(16'7f,16'0f,16'5),
494    _),
495    buselement(bridge, addr(16'7f,16'10,16'0),
496    _),
497    buselement(bridge, addr(16'7f,16'10,16'1),
498    _),
499    buselement(bridge, addr(16'7f,16'10,16'2),
500    _),
501    buselement(bridge, addr(16'7f,16'10,16'3),
502    _),
503    buselement(bridge, addr(16'7f,16'10,16'4),
504    _),
505    buselement(bridge, addr(16'7f,16'10,16'5),
506    _),
507    buselement(bridge, addr(16'7f,16'10,16'6),
508    _),
509    buselement(bridge, addr(16'7f,16'10,16'7),
510    _),
511    buselement(bridge, addr(16'7f,16'13,16'0),
512    _),
513    buselement(bridge, addr(16'7f,16'13,16'1),
514    _),
515    buselement(bridge, addr(16'7f,16'13,16'4),
516    _),
517    buselement(bridge, addr(16'7f,16'13,16'5),
518    _),
519    buselement(bridge, addr(16'7f,16'13,16'6),
520    _),
521    buselement(bridge, addr(16'7f,16'16,16'0),
522    _),
523    buselement(bridge, addr(16'7f,16'16,16'1),
524    _),
525    buselement(bridge, addr(16'7f,16'16,16'2),
526    _),
527    buselement(bridge, addr(16'80,16'01,16'0),
528    secondary(16'81),
529    m(16'fff00000,16'000fffff),
530    p(16'00000000fff00000,16'00000000000fffff),
531    _),
532    buselement(bridge, addr(16'80,16'02,16'0),
533    secondary(16'82),
534    m(16'ec000000,16'ec0fffff),
535    p(16'0000380600000000,16'00003807ffffffff),
536    _),
537    buselement(bridge, addr(16'80,16'03,16'0),
538    secondary(16'83),
539    m(16'fff00000,16'000fffff),
540    p(16'00000000fff00000,16'00000000000fffff),
541    _),
542    buselement(bridge, addr(16'80,16'03,16'2),
543    secondary(16'84),
544    m(16'fff00000,16'000fffff),
545    p(16'00000000fff00000,16'00000000000fffff),
546    _),
547    buselement(bridge, addr(16'80,16'04,16'0),
548    _),
549    buselement(bridge, addr(16'80,16'04,16'1),
550    _),
551    buselement(bridge, addr(16'80,16'04,16'2),
552    _),
553    buselement(bridge, addr(16'80,16'04,16'3),
554    _),
555    buselement(bridge, addr(16'80,16'04,16'4),
556    _),
557    buselement(bridge, addr(16'80,16'04,16'5),
558    _),
559    buselement(bridge, addr(16'80,16'04,16'6),
560    _),
561    buselement(bridge, addr(16'80,16'04,16'7),
562    _),
563    buselement(bridge, addr(16'80,16'05,16'0),
564    _),
565    buselement(bridge, addr(16'80,16'05,16'1),
566    _),
567    buselement(bridge, addr(16'80,16'05,16'2),
568    _),
569    buselement(bridge, addr(16'80,16'05,16'4),
570    _),
571    buselement(bridge, addr(16'82,16'00,16'0),
572    _)].
573
574
575%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
576% small tools
577%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
578
579adjust_range(X, buselement(T,A,Sec,B1,H1,S,Tp,PF, PCIe, Bits), buselement(T,A,Sec,B2,H2,S,Tp,PF, PCIe, Bits)) :-
580    B2 is B1 + X,
581    H2 is H1 + X.
582
583back_to_bytes(Granularity, buselement(T,A,Sec,BP,HP,SP,Tp,PF, PCIe, Bits), buselement(T,A,Sec,B,H,S,Tp,PF, PCIe, Bits)) :-
584    B is BP * Granularity,
585    H is HP * Granularity,
586    S is SP * Granularity.
587
588
589%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
590% the main part of the allocation. Called once per root bridge
591%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
592
593bridge_assignment(Plan, Root, Granularity, ExclRanges, IOAPICs) :-
594    root(Addr,childbus(MinBus,MaxBus),mem(LMem,HMem)) = Root,
595    X is HMem - LMem,
596    Type = mem,
597
598% prefetchable
599    constrain_bus(Granularity, Type, prefetchable, Addr,MinBus,MaxBus,LMem,HMem,BusElementListP),
600    RBaseP::[LMem..HMem],
601    RHighP::[LMem..HMem],
602    RSizeP::[0..X],
603    devicetree(BusElementListP,buselement(bridge,Addr,secondary(MinBus),RBaseP,RHighP,RSizeP, Type, prefetchable, _, _),TP),
604
605% nonprefetchable
606    constrain_bus(Granularity, Type, nonprefetchable, Addr,MinBus,MaxBus,LMem,HMem,BusElementListNP),
607    RBaseNP::[LMem..HMem],
608    RHighNP::[LMem..HMem],
609    RSizeNP::[0..X],
610    devicetree(BusElementListNP,buselement(bridge,Addr,secondary(MinBus),RBaseNP,RHighNP,RSizeNP, Type, nonprefetchable, _, _),TNP),
611
612% pseudo-root of both trees
613    PseudoBase::[LMem..HMem],
614    PseudoHigh::[LMem..HMem],
615    PseudoSize::[0..X],
616    T = t(buselement(bridge, addr(-1, -1, -1), childbus(-1, -1), PseudoBase, PseudoHigh, PseudoSize, _, _, _, _), [TP, TNP]),
617    setrange(T,_,_,_),
618    nonoverlap(T),
619    naturally_aligned(T, 256, LMem, HMem),
620    tree2list(T,ListaU),
621    sort(6, >=, ListaU, Lista),
622    not_overlap_memory_ranges(Lista, ExclRanges),
623    keep_orig_addr(Lista, 12, 3, _, _, _, _),
624    keep_ioapic_bars(Lista, IOAPICs),
625    labelall(Lista),
626    subtract(Lista,[buselement(bridge,Addr,_,_,_,_,_,prefetchable,_,_)],Pl3),
627    subtract(Pl3,[buselement(bridge,Addr,_,_,_,_,_,nonprefetchable,_,_)],Pl2),
628    subtract(Pl2,[buselement(bridge,addr(-1,-1,-1),_,_,_,_,_,_,_,_)],Pl),
629    maplist(adjust_range(0),Pl,PR),
630    maplist(back_to_bytes(Granularity),PR,Plan).
631
632% dot output:
633%    PrBaseBytePref is RBaseP * Granularity,
634%    PrHighBytePref is RHighP * Granularity,
635%    PrBaseByteNonPref is RBaseNP * Granularity,
636%    PrHighByteNonPref is RHighNP * Granularity,
637%    plan_to_dot(Granularity, Plan, Root, PrBaseBytePref, PrHighBytePref, PrBaseByteNonPref, PrHighByteNonPref).
638
639
640%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
641% instantiating the variables
642%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
643
644
645labelall(BusElementList) :-
646    maplist(base, BusElementList, Base),
647    maplist(high, BusElementList, High),
648    maplist(size, BusElementList, Size),
649    append(Base, High, L1),
650    append(L1, Size, L2),
651    labeling(L2).
652
653
654
655%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
656% create the list of devices and bridges in form of buselements and create the
657% variables.
658% we care about the allocation of memory mapped registers here, therefore we only
659% look at bar located in "mem", not "io"
660%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
661
662constrain_bus(Granularity, Type, Prefetch, RootAddr,Bus,MaxBus,LMem,HMem,OutBusElementList) :-
663    constrain_bus_ex(Granularity, Type, Prefetch, RootAddr,Bus,MaxBus,LMem,HMem,[],OutBusElementList).
664
665constrain_bus_ex(_, _, _, _,Bus,MaxBus,_,_,InL,InL) :- Bus > MaxBus.
666constrain_bus_ex(Granularity, Type, Prefetch, RootAddr,Bus,MaxBus,LMem,HMem,InBusElementList,OutBusElementList) :-
667    Bus =< MaxBus,
668    SMax is HMem - LMem,
669    ( is_predicate(bridge/8) ->
670	    findall(buselement(bridge,addr(Bus,Dev,Fun),secondary(Sec),Base,High,Size,Type,Prefetch, PCIe, 0),
671	            ( bridge(PCIe, addr(Bus,Dev,Fun), _, _, _, _, _, secondary(Sec)),
672	              not addr(Bus,Dev,Fun) = RootAddr,
673	              Base::[LMem..HMem],High::[LMem..HMem],Size::[0..SMax]
674	            ),BridgeList);
675        BridgeList = []
676    ),
677    ( is_predicate(device/8) ->
678	    findall(buselement(device,addr(Bus,Dev,Fun),BAR,Base,High,SizeP,Type,Prefetch, PCIe, Bits),
679	            ( device(PCIe, addr(Bus,Dev,Fun),_,_,_,_,_,_),
680	              bar(addr(Bus,Dev,Fun),BAR,_,Size, Type, Prefetch, Bits),
681	              Base::[LMem..HMem],High::[LMem..HMem],
682	              ST1 is Size / Granularity,
683	              ceiling(ST1, ST2),
684	              integer(ST2, SizeP)
685	            ),DeviceList);
686        DeviceList = []
687    ),
688    append(BridgeList, DeviceList, MyBusElementList),
689    append(InBusElementList, MyBusElementList, NewBusElementList),
690    NextBus is Bus + 1,
691    constrain_bus_ex(Granularity, Type, Prefetch, RootAddr, NextBus, MaxBus, LMem,HMem,NewBusElementList,OutBusElementList).
692
693
694%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
695% create the PCI(e) device tree from a list of "buselement" and return it in Tree
696%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
697
698devicetree(List,CurrRoot,Tree) :-
699    buselement(bridge,_,secondary(Sec),_,_,_,_,_,_,_) = CurrRoot,
700    findall(X,(
701               member(Y,List),
702               buselement(_,addr(Sec,_,_),_,_,_,_,_,_,_,_) = Y,
703               devicetree(List, Y, X)),Children
704           ),
705    Tree = t(CurrRoot,Children).
706devicetree(_,CurrRoot,Tree) :-
707    buselement(device,_,_,_,_,_,_,_,_,_) = CurrRoot,
708    Tree = t(CurrRoot, []).
709
710
711%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
712% convert a tree to a list of buselements
713%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
714
715tree2list([],[]).
716tree2list(Tree, List) :-
717    t(Node,Children) = Tree,
718    ( foreach(El,Children),
719      foreach(L1,ChildList)
720      do
721        tree2list(El,L1)
722    ),
723    flatten(ChildList,L2),
724    List = [Node|L2].
725
726
727
728%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
729% store the new values of the BARs
730%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
731replace_current_BAR_values(L) :-
732    delete_current_BAR_values(L),
733    store_current_BAR_values(L).
734
735store_current_BAR_values([]).
736store_current_BAR_values([H|T]) :-
737    ( buselement(device,Addr,BAR,Base,High,Size,_,_,_,_) = H ->
738         assert(currentbar(Addr,BAR,Base,High,Size));
739        true
740    ),
741    store_current_BAR_values(T).
742
743
744delete_current_BAR_values([]).
745delete_current_BAR_values([H|T]) :-
746    ( buselement(device,Addr,BAR,_,_,_,_,_,_,_) = H ->
747        ( currentbar(Addr,BAR,_,_,_) ->
748            retract(currentbar(Addr,BAR,_,_,_));
749            true
750        );
751        true
752    ),
753    delete_current_BAR_values(T).
754
755
756
757
758%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
759% add constraints to the tree
760%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
761
762% make sure that the bridge has a range which includes all the children
763setrange(Tree,SubTreeSize,SubTreeMin,SubTreeMax) :-
764    t(Node,Children) = Tree,
765    ( foreach(El,Children),
766      foreach(Sz,SizeList),
767      foreach(Mi,MinList),
768      foreach(Ma,MaxList)
769      do
770        setrange(El,Sz,Mi,Ma)
771    ),
772    ic_global:sumlist(SizeList,Size),
773    buselement(_,_,_,Base,High,ElemSize,_,_,_,_) = Node,
774    ElemSize $>= Size,
775    ( not MinList=[] ->
776        ic:minlist(MinList,Min),
777        ic:maxlist(MaxList,Max),
778        Min $>= Base,
779        Max $=< High;
780        true
781    ),
782    High $= Base + ElemSize,
783    SubTreeSize $= ElemSize,
784    SubTreeMin $= Base,
785    SubTreeMax $= High.
786setrange([],0,_,_).
787
788
789% make sure that the children do not overlap
790child(t(C,_),C).
791nonoverlap(Tree) :-
792    t(_ ,Children) = Tree,
793    maplist(child,Children,ChildList),
794    ( not ChildList=[] ->
795        maplist(base,ChildList,Base),
796        maplist(size,ChildList,Size),
797        disjunctive(Base,Size);
798        true
799    ),
800    ( foreach(El, Children)
801      do
802        nonoverlap(El)
803    ).
804
805
806naturally_aligned(Tree, BridgeAlignment, LMem, HMem) :-
807    t(Node,Children) = Tree,
808    ( buselement(device,_,_,Base,High,Size,_,_,_,_) = Node ->
809      Divisor is Size
810      ;
811      buselement(bridge,_,_,Base,High,_,_,_,_,_) = Node ->
812      Divisor is BridgeAlignment
813    ),
814
815    T1 is (HMem - LMem) / Divisor,
816    ceiling(T1, T2),
817    integer(T2, Nr),
818    N::[0..Nr],
819    N2::[0..Nr],
820    mod(LMem,Divisor,Remainder),
821    ( Remainder =:= 0 ->
822        Corr is 0;
823        Corr is Divisor - Remainder
824    ),
825    Base $= N*Divisor + LMem + Corr,
826    High $>= Base,
827    High $= N2*Divisor + LMem + Corr,
828    ( foreach(El, Children),
829      param(BridgeAlignment),
830      param(LMem),
831      param(HMem)
832      do
833        naturally_aligned(El, BridgeAlignment, LMem, HMem)
834    ).
835
836
837% do not overlap with the given list of memory ranges
838not_overlap_memory_ranges([], _).
839not_overlap_memory_ranges(_, []).
840not_overlap_memory_ranges([buselement(bridge,_,_,_,_,_,_,_,_,_)|PCIList], MemoryRanges) :-
841    not_overlap_memory_ranges(PCIList, MemoryRanges).
842not_overlap_memory_ranges([H|PCIList], MemoryRanges) :-
843    ( foreach(range(RBase,RSize),MemoryRanges),
844      param(H)
845      do
846      buselement(device,_,_,Base,_,Size,_,_,_,_) = H,
847      append([Base],[RBase],Bases),
848      append([Size],[RSize],Sizes),
849      disjunctive(Bases,Sizes)
850    ),
851    not_overlap_memory_ranges(PCIList, MemoryRanges).
852
853
854keep_orig_addr([], _, _, _, _, _, _).
855keep_orig_addr([H|Buselements], Class, SubClass, ProgIf, Bus, Dev, Fun) :-
856    ( buselement(device,addr(Bus,Dev,Fun),BAR,Base,_,_,_,_,_,_) = H,device(_,addr(Bus,Dev,Fun),_,_,Class, SubClass, ProgIf,_),bar(addr(Bus,Dev,Fun),BAR,OrigBase,_,_,_,_) ->
857       T1 is OrigBase / 4096,
858       floor(T1,T2),
859       integer(T2,KeepBase),
860        Base $= KeepBase;
861        true
862    ),
863    keep_orig_addr(Buselements, Class, SubClass, ProgIf, Bus, Dev, Fun).
864
865% on some machines (sbrinz1) one of the two IOAPICs appears as a BAR
866% on a device which claims to be a RAM memory controller. If this occurs,
867% we want to avoid moving this BAR as otherwise the IOAPIC cannot be reached
868% anymore.
869keep_ioapic_bars(_, []).
870keep_ioapic_bars(Buselements, [H|IOAPICList]) :-
871    (
872    range(B, _) = H,
873    bar(addr(Bus,Dev,Fun),_,OrigBase,_,_,_,_),
874    T1 is OrigBase / 4096,
875    floor(T1,T2),
876    integer(T2,KeepBase),
877    KeepBase =:= B ->
878    keep_orig_addr(Buselements, _, _, _, Bus, Dev, Fun);
879    true
880    ),
881    keep_ioapic_bars(Buselements, IOAPICList).
882