blob: 4edae1b367703b2379a06331fd3b366af9aefdbd [file] [log] [blame]
lowRISC Contributors802543a2019-08-31 12:12:56 +01001# Copyright lowRISC contributors.
2# Licensed under the Apache License, Version 2.0, see LICENSE for details.
3# SPDX-License-Identifier: Apache-2.0
4
lowRISC Contributors802543a2019-08-31 12:12:56 +01005import logging as log
6
Eunchan Kim837c7962020-04-30 12:15:49 -07007from .item import Node, NodeType
lowRISC Contributors802543a2019-08-31 12:12:56 +01008from .xbar import Xbar
9
10
Eunchan Kim837c7962020-04-30 12:15:49 -070011def elaborate(xbar: Xbar) -> bool:
lowRISC Contributors802543a2019-08-31 12:12:56 +010012 """elaborate reads all nodes and edges then
13 construct internal FIFOs, Sockets.
14 """
15 # Condition check
16 if len(xbar.nodes) <= 1 or len(xbar.edges) == 0:
17 log.error(
18 "# of Nodes is less than 2 or no Edge exists. Cannot proceed.")
19 return False
20
21 for host in xbar.hosts:
22 process_node(host, xbar)
23 log.info("Node Processed: " + repr(xbar))
24
Eunchan Kim837c7962020-04-30 12:15:49 -070025 # Pipeline
lowRISC Contributors802543a2019-08-31 12:12:56 +010026 process_pipeline(xbar)
27
Eunchan Kim837c7962020-04-30 12:15:49 -070028 # Build address map
29 # Each socket_1n should have address map
lowRISC Contributors802543a2019-08-31 12:12:56 +010030
lowRISC Contributors802543a2019-08-31 12:12:56 +010031 return True
32
33
34def process_node(node, xbar): # node: Node -> xbar: Xbar -> Xbar
35 """process each node based on algorithm
36
37 1. If a node has different clock from main clock and not ASYNC_FIFO:
38 a. (New Node) Create ASYNC_FIFO node.
39 b. Revise every edges from the node to have start node as ASYNC_FIFO
40 node. (New Edge) create a edge from the node to ASYNC_FIFO node.
41 - Repeat the algorithm with ASYNC_FIFO node.
42 c. Revise every edges to the node to have end node as ASYNC_FIFO
43 node. (New Edge) create a edge from ASYNC_FIFO node to the node.
44 d. If it is not DEVICE, HOST node, raise Error. If it is DEVICE, end
45 (next item).
46 2. If a node has multiple edges having it as a end node and not SOCKET_M1:
47 a. (New node) Create SOCKET_M1 node.
48 b. Revise every edges to the node to have SOCKET_M1 node as end node.
49 c. (New Edge) create a edge from SOCKET_M1 to the node.
50 d. Repeat the algorithm with the node.
51 3. If a node has multiple edges having it as a start node and not SOCKET_1N:
52 a. (New node) Create SOCKET_1N node.
53 b. Revise every edges from the node to have SOCKET_1N node as start node.
54 c. (New Edge) Create a edge from the node to SOCKET_1N node.
Scott Johnson4e353842020-01-17 17:14:35 -080055 d. (for loop) Repeat the algorithm with SOCKET_1N's other side node.
lowRISC Contributors802543a2019-08-31 12:12:56 +010056 """
57
58 # If a node has different clock from main clock and not ASYNC_FIFO:
59 if node.node_type != NodeType.ASYNC_FIFO and node.clocks[0] != xbar.clock:
60 # (New Node) Create ASYNC_FIFO node
61 new_node = Node(name="asf_" + str(len(xbar.nodes)),
62 node_type=NodeType.ASYNC_FIFO,
Weicai Yanga495d202019-12-05 15:36:27 -080063 clock=xbar.clock,
64 reset=xbar.reset)
Timothy Chene8cc63e2019-10-09 16:30:58 -070065
Timothy Chen09d859b2019-11-08 14:01:12 -080066 # if node is HOST, host clock synchronizes into xbar domain
67 # if node is DEVICE, xbar synchronizes into device clock domain
lowRISC Contributors802543a2019-08-31 12:12:56 +010068 if node.node_type == NodeType.HOST:
69 new_node.clocks.insert(0, node.clocks[0])
Timothy Chen09d859b2019-11-08 14:01:12 -080070 new_node.resets.insert(0, node.resets[0])
lowRISC Contributors802543a2019-08-31 12:12:56 +010071 else:
72 new_node.clocks.append(node.clocks[0])
Timothy Chen09d859b2019-11-08 14:01:12 -080073 new_node.resets.append(node.resets[0])
lowRISC Contributors802543a2019-08-31 12:12:56 +010074
75 xbar.insert_node(new_node, node)
76
77 process_node(new_node, xbar)
78
79 # If a node has multiple edges having it as a end node and not SOCKET_M1:
80 elif node.node_type != NodeType.SOCKET_M1 and len(node.us) > 1:
81 # (New node) Create SOCKET_M1 node
82 new_node = Node(name="sm1_" + str(len(xbar.nodes)),
83 node_type=NodeType.SOCKET_M1,
Weicai Yanga495d202019-12-05 15:36:27 -080084 clock=xbar.clock,
85 reset=xbar.reset)
Timothy Chena37d6e42020-06-18 11:43:20 -070086
87 # By default, assume connecting to SOCKET_1N upstream and bypass all FIFOs
88 # If upstream requires pipelining, it will be added through process pipeline
89 new_node.hdepth = 0
Timothy Chen1299fa12022-03-22 18:21:02 -070090 new_node.hreq_pass = 2**len(node.us) - 1
91 new_node.hrsp_pass = 2**len(node.us) - 1
Timothy Chena37d6e42020-06-18 11:43:20 -070092 new_node.ddepth = 0
Timothy Chen1299fa12022-03-22 18:21:02 -070093 new_node.dreq_pass = 1
94 new_node.drsp_pass = 1
lowRISC Contributors802543a2019-08-31 12:12:56 +010095 xbar.insert_node(new_node, node)
96 process_node(new_node, xbar)
97
98 # If a node has multiple edges having it as a start node and not SOCKET_1N:
99 elif node.node_type != NodeType.SOCKET_1N and len(node.ds) > 1:
100 # (New node) Create SOCKET_1N node
101 new_node = Node(name="s1n_" + str(len(xbar.nodes)),
102 node_type=NodeType.SOCKET_1N,
Weicai Yanga495d202019-12-05 15:36:27 -0800103 clock=xbar.clock,
104 reset=xbar.reset)
Timothy Chena37d6e42020-06-18 11:43:20 -0700105
106 # By default, assume connecting to SOCKET_M1 downstream and bypass all FIFOs
107 # If upstream requires pipelining, it will be added through process pipeline
108 new_node.hdepth = 0
Timothy Chen1299fa12022-03-22 18:21:02 -0700109 new_node.hreq_pass = 1
110 new_node.hrsp_pass = 1
Timothy Chena37d6e42020-06-18 11:43:20 -0700111 new_node.ddepth = 0
Timothy Chen1299fa12022-03-22 18:21:02 -0700112 new_node.dreq_pass = 2**len(node.ds) - 1
113 new_node.drsp_pass = 2**len(node.ds) - 1
lowRISC Contributors802543a2019-08-31 12:12:56 +0100114 xbar.insert_node(new_node, node)
115
116 # (for loop) Repeat the algorithm with SOCKET_1N's other side node
117 for edge in new_node.ds:
118 process_node(edge.ds, xbar)
119
120 return xbar
121
122
123def process_pipeline(xbar):
Timothy Chen61e25e82019-09-13 14:04:10 -0700124 """Check if HOST, DEVICE has settings different from default, then propagate it to end
lowRISC Contributors802543a2019-08-31 12:12:56 +0100125 """
126 for host in xbar.hosts:
Timothy Chen61e25e82019-09-13 14:04:10 -0700127 # go downstream and change the HReqPass/Depth at the first instance.
lowRISC Contributors802543a2019-08-31 12:12:56 +0100128 # If it is async, skip.
Timothy Chen61e25e82019-09-13 14:04:10 -0700129 # If Socket 1N,
130 # if pipeline True and bypass false, set hpass to 0
131 # if pipeline is False, set depth to 0
132 # If Socket M1, find position of the host and follow procedure above
lowRISC Contributors802543a2019-08-31 12:12:56 +0100133 # If it is device, it means host and device are directly connected. Ignore now.
134
Timothy Chena37d6e42020-06-18 11:43:20 -0700135 log.info("Processing pipeline for host {}".format(host.name))
lowRISC Contributors802543a2019-08-31 12:12:56 +0100136
Timothy Chen1299fa12022-03-22 18:21:02 -0700137 fifo_pass = host.req_fifo_pass or host.rsp_fifo_pass
138
Timothy Chena37d6e42020-06-18 11:43:20 -0700139 # FIFO present with no passthrough option
140 # FIFO present with passthrough option
141 # FIFO not present and full passthrough
142 full_fifo = False
143 fifo_passthru = False
144 full_passthru = True
Timothy Chen1299fa12022-03-22 18:21:02 -0700145 if host.pipeline is True and fifo_pass is False:
Timothy Chena37d6e42020-06-18 11:43:20 -0700146 full_fifo = True
147
Timothy Chen1299fa12022-03-22 18:21:02 -0700148 elif host.pipeline is True and fifo_pass is True:
Timothy Chena37d6e42020-06-18 11:43:20 -0700149 fifo_passthru = True
150
151 elif host.pipeline is False:
152 full_passthru = True
153
lowRISC Contributors802543a2019-08-31 12:12:56 +0100154 dnode = host.ds[0].ds
Timothy Chene8cc63e2019-10-09 16:30:58 -0700155
156 if dnode.node_type == NodeType.ASYNC_FIFO:
157 continue
158
Timothy Chen1299fa12022-03-22 18:21:02 -0700159 req_pass = 1 if host.req_fifo_pass else 0
160 rsp_pass = 1 if host.rsp_fifo_pass else 0
lowRISC Contributors802543a2019-08-31 12:12:56 +0100161 if dnode.node_type == NodeType.SOCKET_1N:
Timothy Chena37d6e42020-06-18 11:43:20 -0700162 if full_fifo:
Timothy Chen1299fa12022-03-22 18:21:02 -0700163 dnode.hreq_pass = 0
164 dnode.hrsp_pass = 0
Timothy Chena37d6e42020-06-18 11:43:20 -0700165 dnode.hdepth = 2
166 elif fifo_passthru:
Timothy Chen1299fa12022-03-22 18:21:02 -0700167 dnode.hreq_pass = req_pass
168 dnode.hrsp_pass = rsp_pass
Timothy Chena37d6e42020-06-18 11:43:20 -0700169 dnode.hdepth = 2
170 elif full_passthru:
Timothy Chen1299fa12022-03-22 18:21:02 -0700171 dnode.hreq_pass = 1
172 dnode.hrsp_pass = 1
Timothy Chena37d6e42020-06-18 11:43:20 -0700173 dnode.hdepth = 0
174
Weicai Yang53b0d4d2020-11-30 15:28:33 -0800175 log.info(
Timothy Chen1299fa12022-03-22 18:21:02 -0700176 "Finished processing socket1n {}, req pass={}, rsp pass={}, depth={}".format(
177 dnode.name, dnode.hreq_pass, dnode.hrsp_pass, dnode.hdepth))
Timothy Chen61e25e82019-09-13 14:04:10 -0700178
lowRISC Contributors802543a2019-08-31 12:12:56 +0100179 elif dnode.node_type == NodeType.SOCKET_M1:
Jan Van Winkel0fb3e172020-09-03 12:52:08 +0200180 idx = dnode.us.index(host.ds[0])
Timothy Chen1299fa12022-03-22 18:21:02 -0700181
182 # first clear out entry
183 dnode.hreq_pass = dnode.hreq_pass & ~(1 << idx)
184 dnode.hreq_pass = dnode.hreq_pass & ~(1 << idx)
Timothy Chena37d6e42020-06-18 11:43:20 -0700185 if full_fifo:
186 log.info("fifo present no bypass")
Timothy Chena37d6e42020-06-18 11:43:20 -0700187 dnode.hdepth = dnode.hdepth | (2 << idx * 4)
188 elif fifo_passthru:
189 log.info("fifo present with bypass")
Timothy Chen1299fa12022-03-22 18:21:02 -0700190 dnode.hreq_pass = dnode.hreq_pass | (req_pass << idx)
191 dnode.hreq_pass = dnode.hrsp_pass | (rsp_pass << idx)
Timothy Chena37d6e42020-06-18 11:43:20 -0700192 dnode.hdepth = dnode.hdepth | (2 << idx * 4)
193 elif full_passthru:
194 log.info("fifo not present")
Timothy Chen1299fa12022-03-22 18:21:02 -0700195 dnode.hreq_pass = dnode.hreq_pass | (1 << idx)
196 dnode.hreq_pass = dnode.hrsp_pass | (1 << idx)
Timothy Chena37d6e42020-06-18 11:43:20 -0700197 dnode.hdepth = dnode.hdepth & ~(0xF << idx * 4)
Timothy Chen61e25e82019-09-13 14:04:10 -0700198
Weicai Yang53b0d4d2020-11-30 15:28:33 -0800199 log.info(
Timothy Chen1299fa12022-03-22 18:21:02 -0700200 "Finished processing socketm1 {}, req pass={}, rsp pass={}, depth={}".format(
201 dnode.name, dnode.hreq_pass, dnode.hrsp_pass, dnode.hdepth))
lowRISC Contributors802543a2019-08-31 12:12:56 +0100202
203 for device in xbar.devices:
204 # go upstream and set DReq/RspPass at the first instance.
205 # If it is async, skip
Timothy Chen61e25e82019-09-13 14:04:10 -0700206 # If Socket M1
207 # If pipeline True and bypass False, set dpass to 0
208 # If pipeline False, set depth to 0
209 # If Socket 1N, find position of the device and follow procedure above
lowRISC Contributors802543a2019-08-31 12:12:56 +0100210 # If it is host, ignore
211
Timothy Chena37d6e42020-06-18 11:43:20 -0700212 log.info("Processing pipeline for device {}".format(device.name))
lowRISC Contributors802543a2019-08-31 12:12:56 +0100213
Timothy Chena37d6e42020-06-18 11:43:20 -0700214 # FIFO present with no passthrough option
215 # FIFO present with passthrough option
216 # FIFO not present and full passthrough
Timothy Chen1299fa12022-03-22 18:21:02 -0700217 fifo_pass = device.req_fifo_pass or device.rsp_fifo_pass
Timothy Chena37d6e42020-06-18 11:43:20 -0700218 full_fifo = False
219 fifo_passthru = False
220 full_passthru = True
Timothy Chen1299fa12022-03-22 18:21:02 -0700221 if device.pipeline is True and fifo_pass is False:
Timothy Chena37d6e42020-06-18 11:43:20 -0700222 full_fifo = True
223
Timothy Chen1299fa12022-03-22 18:21:02 -0700224 elif device.pipeline is True and fifo_pass is True:
Timothy Chena37d6e42020-06-18 11:43:20 -0700225 fifo_passthru = True
226
227 elif device.pipeline is False:
228 full_passthru = True
229
lowRISC Contributors802543a2019-08-31 12:12:56 +0100230 unode = device.us[0].us
Timothy Chene8cc63e2019-10-09 16:30:58 -0700231
232 if unode.node_type == NodeType.ASYNC_FIFO:
233 continue
234
Timothy Chen1299fa12022-03-22 18:21:02 -0700235 req_pass = 1 if device.req_fifo_pass else 0
236 rsp_pass = 1 if device.rsp_fifo_pass else 0
lowRISC Contributors802543a2019-08-31 12:12:56 +0100237 if unode.node_type == NodeType.SOCKET_1N:
Eunchan Kimc7452942019-12-19 17:04:37 -0800238 idx = unode.ds.index(device.us[0])
Timothy Chena37d6e42020-06-18 11:43:20 -0700239
Timothy Chen1299fa12022-03-22 18:21:02 -0700240 # first clear out entry
241 unode.dreq_pass = unode.dreq_pass & ~(1 << idx)
242 unode.drsp_pass = unode.drsp_pass & ~(1 << idx)
Timothy Chena37d6e42020-06-18 11:43:20 -0700243 if full_fifo:
Timothy Chena37d6e42020-06-18 11:43:20 -0700244 unode.ddepth = unode.ddepth | (2 << idx * 4)
245 elif fifo_passthru:
Timothy Chen1299fa12022-03-22 18:21:02 -0700246 unode.dreq_pass = unode.dreq_pass | (req_pass << idx)
247 unode.drsp_pass = unode.drsp_pass | (rsp_pass << idx)
Timothy Chena37d6e42020-06-18 11:43:20 -0700248 unode.ddepth = unode.ddepth | (2 << idx * 4)
249 elif full_passthru:
Timothy Chen1299fa12022-03-22 18:21:02 -0700250 unode.dreq_pass = unode.dreq_pass | (1 << idx)
251 unode.drsp_pass = unode.drsp_pass | (1 << idx)
Timothy Chena37d6e42020-06-18 11:43:20 -0700252 unode.ddepth = unode.ddepth & ~(0xF << idx * 4)
253
Timothy Chen1299fa12022-03-22 18:21:02 -0700254 log.info("Finished processing socket1n {}, req pass={:x}, req pass={:x} depth={:x}".
255 format(unode.name, unode.dreq_pass, unode.drsp_pass, unode.ddepth))
Timothy Chen61e25e82019-09-13 14:04:10 -0700256
lowRISC Contributors802543a2019-08-31 12:12:56 +0100257 elif unode.node_type == NodeType.SOCKET_M1:
Timothy Chena37d6e42020-06-18 11:43:20 -0700258 if full_fifo:
259 log.info("Fifo present with no passthrough")
Timothy Chen1299fa12022-03-22 18:21:02 -0700260 unode.dreq_pass = 0
261 unode.drsp_pass = 0
Timothy Chena37d6e42020-06-18 11:43:20 -0700262 unode.ddepth = 2
263 elif fifo_passthru:
264 log.info("Fifo present with passthrough")
Timothy Chen1299fa12022-03-22 18:21:02 -0700265 unode.dreq_pass = req_pass
266 unode.drsp_pass = rsp_pass
Timothy Chena37d6e42020-06-18 11:43:20 -0700267 unode.ddepth = 2
268 elif full_passthru:
269 log.info("No Fifo")
Timothy Chen1299fa12022-03-22 18:21:02 -0700270 unode.dreq_pass = 1
271 unode.drsp_pass = 1
Timothy Chena37d6e42020-06-18 11:43:20 -0700272 unode.ddepth = 0
Timothy Chen61e25e82019-09-13 14:04:10 -0700273
Timothy Chen1299fa12022-03-22 18:21:02 -0700274 log.info("Finished processing socketm1 {}, req pass={:x}, rsp pass={:x}, depth={:x}".
275 format(unode.name, unode.dreq_pass, unode.drsp_pass, unode.ddepth))
lowRISC Contributors802543a2019-08-31 12:12:56 +0100276
277 return xbar