Zynq.AcAxisIo.Mod 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539
  1. (**
  2. AUTHOR "Alexey Morozov, HighDim GmbH, 2015";
  3. PURPOSE "ActiveCells AXI4 Stream IO interface";
  4. *)
  5. MODULE AcAxisIo;
  6. IMPORT
  7. SYSTEM, Platform;
  8. CONST
  9. ChanOffset = 256*4; (* ActiveCells AXI4 Stream channel offset in bytes *)
  10. (*
  11. OutDataOffset = 0;
  12. OutReadyOffset = SIZEOF(LONGINT);
  13. InpAvailableOffset = 0;
  14. InpDataOffset = 2*SIZEOF(LONGINT);
  15. *)
  16. TYPE
  17. (* AXI4 Stream port descriptor *)
  18. PortDesc = RECORD
  19. lockAddr: ADDRESS; (** *)
  20. portAddr: ADDRESS;
  21. END;
  22. Output* = PORT OUT; (** AXI4 Stream output port *)
  23. Input* = PORT IN; (** AXI4 Stream input port *)
  24. VAR
  25. inputs: ARRAY 2 OF ARRAY 256 OF PortDesc;
  26. outputs: ARRAY 2 OF ARRAY 256 OF PortDesc;
  27. locks: ARRAY 2 OF LONGINT; (* locks for each physical channel *)
  28. (*
  29. (** AXI4 Stream output interface *)
  30. Output* = POINTER{UNSAFE,UNTRACED} TO RECORD
  31. data: LONGINT; (** output data, write only *)
  32. ready: BOOLEAN; (** TRUE when output is available for sending data *)
  33. padding: ARRAY 3 OF CHAR;
  34. END;
  35. (** AXI4 Stream input port description *)
  36. Input* = POINTER{UNSAFE,UNTRACED} TO RECORD
  37. available: BOOLEAN; (** TRUE when input data is available *)
  38. padding: ARRAY 7 OF CHAR;
  39. data: LONGINT; (** input data, read only *)
  40. END;
  41. *)
  42. (**
  43. Get AXI4 Stream input port
  44. physicalPortNum: physical port number
  45. logicalPortNum: logical port number
  46. *)
  47. PROCEDURE GetInput*(physicalPortNum, logicalPortNum: LONGINT; VAR port: Input): BOOLEAN;
  48. VAR
  49. portDesc: POINTER {UNSAFE} TO PortDesc;
  50. portAddr: ADDRESS;
  51. BEGIN
  52. CASE physicalPortNum OF
  53. |0: portAddr := Platform.MasterAxiGp0Base + logicalPortNum*ChanOffset;
  54. |1: portAddr := Platform.MasterAxiGp1Base + logicalPortNum*ChanOffset;
  55. ELSE
  56. RETURN FALSE;
  57. END;
  58. portDesc := ADDRESSOF(inputs[physicalPortNum,logicalPortNum]);
  59. portDesc.portAddr := portAddr;
  60. portDesc.lockAddr := ADDRESSOF(locks[physicalPortNum]);
  61. port := SYSTEM.VAL(Input,portDesc);
  62. RETURN TRUE;
  63. END GetInput;
  64. (**
  65. Get AXI4 Stream output port
  66. physicalPortNum: physical port number
  67. logicalPortNum: logical port number
  68. *)
  69. PROCEDURE GetOutput*(physicalPortNum, logicalPortNum: LONGINT; VAR port: Output): BOOLEAN;
  70. VAR
  71. portDesc: POINTER {UNSAFE} TO PortDesc;
  72. portAddr: ADDRESS;
  73. BEGIN
  74. CASE physicalPortNum OF
  75. |0: portAddr := Platform.MasterAxiGp0Base + logicalPortNum*ChanOffset;
  76. |1: portAddr := Platform.MasterAxiGp1Base + logicalPortNum*ChanOffset;
  77. ELSE
  78. RETURN FALSE;
  79. END;
  80. portDesc := ADDRESSOF(outputs[physicalPortNum,logicalPortNum]);
  81. portDesc.portAddr := portAddr;
  82. portDesc.lockAddr := ADDRESSOF(locks[physicalPortNum]);
  83. port := SYSTEM.VAL(Output,portDesc);
  84. RETURN TRUE;
  85. END GetOutput;
  86. PROCEDURE GetOutputDataAddr*(out: Output): ADDRESS;
  87. VAR portDesc: POINTER {UNSAFE} TO PortDesc;
  88. BEGIN
  89. portDesc := SYSTEM.VAL(ADDRESS,out);
  90. ASSERT(portDesc # NIL);
  91. RETURN portDesc.portAddr;
  92. END GetOutputDataAddr;
  93. PROCEDURE GetInputDataAddr*(inp: Input): ADDRESS;
  94. VAR portDesc: POINTER {UNSAFE} TO PortDesc;
  95. BEGIN
  96. portDesc := SYSTEM.VAL(ADDRESS,inp);
  97. ASSERT(portDesc # NIL);
  98. RETURN portDesc.portAddr+8;
  99. END GetInputDataAddr;
  100. (*
  101. Acquire exclusive access to a resource
  102. R1: lock address
  103. R0, R5 are used in addition
  104. Based on the code presented in "Barrier Litmus Tests and Cookbook" by Richard Grisenthwaite, ARM, 26.11.2009,
  105. *)
  106. PROCEDURE {NOPAF} -AcquireResource;
  107. CODE
  108. MOV R0, #1
  109. Loop:
  110. LDREX R5, R1 ; read lock
  111. CMP R5, #0 ; check if 0
  112. WFENE ; sleep if the lock is held
  113. STREXEQ R5, R0, R1 ; attempt to store new value
  114. CMPEQ R5, #0 ; test if store suceeded
  115. BNE Loop ; retry if not
  116. DMB ; ensures that all subsequent accesses are observed after the gaining of the lock is observed
  117. ; loads and stores in the critical region can now be performed
  118. END AcquireResource;
  119. (*
  120. Release exclusive access to a resource
  121. R1: lock address
  122. R0 is used in addition
  123. Based on the code presented in "Barrier Litmus Tests and Cookbook" by Richard Grisenthwaite, ARM, 26.11.2009,
  124. *)
  125. PROCEDURE {NOPAF} -ReleaseResource;
  126. CODE
  127. MOV R0, #0
  128. DMB ; ensure all previous accesses are observed before the lock is cleared
  129. STR R0, [R1, #0]
  130. ; clear the lock.
  131. DSB ; ensure completion of the store that cleared the lock before sending the event
  132. SEV
  133. END ReleaseResource;
  134. (*PROCEDURE AcquireObject(lockAddr: ADDRESS);
  135. BEGIN
  136. CODE
  137. LDR R1, [FP, #lockAddr] ; R1 := address of lock
  138. END;
  139. AcquireResource;
  140. END AcquireObject;
  141. PROCEDURE ReleaseObject(lockAddr: ADDRESS);
  142. BEGIN
  143. CODE
  144. LDR R1, [FP, #lockAddr] ; R1 := address of lock
  145. END;
  146. ReleaseResource
  147. END ReleaseObject;*)
  148. (**
  149. Returns TRUE if the given output port is ready to accept new data
  150. *)
  151. PROCEDURE Ready*(out: Output): BOOLEAN;
  152. VAR b: BOOLEAN;
  153. (*VAR p: POINTER {UNSAFE} TO PortDesc;*)
  154. BEGIN
  155. CODE
  156. LDR R3, [FP, #out] ; R3 := address of PortDesc.lockAddr
  157. LDR R1, [R3, #0] ; R1 := PortDesc.lockAddr
  158. END;
  159. AcquireResource;
  160. CODE
  161. LDR R3, [R3, #4] ; R3 := PortDesc.portAddr
  162. LDR R4, [R3, #4] ; R4 := out.Ready
  163. STRB R4, [FP, #b] ; b := R4
  164. END;
  165. ReleaseResource;
  166. (*p := SYSTEM.VAL(ADDRESS,out);
  167. AcquireObject(p.lockAddr);
  168. b := SYSTEM.VAL(BOOLEAN,SYSTEM.GET32(p.portAddr+OutReadyOffset));
  169. ReleaseObject(p.lockAddr);*)
  170. RETURN b;
  171. END Ready;
  172. (** Returns number of data elements available to read from an input port *)
  173. PROCEDURE Available*(inp: Input): LONGINT;
  174. VAR available: LONGINT;
  175. (*VAR p: POINTER {UNSAFE} TO PortDesc;*)
  176. BEGIN
  177. CODE
  178. LDR R3, [FP, #inp] ; R3 := address of PortDesc.lockAddr
  179. LDR R1, [R3, #0] ; R1 := PortDesc.lockAddr
  180. END;
  181. AcquireResource;
  182. CODE
  183. LDR R3, [R3, #4] ; R3 := PortDesc.portAddr
  184. LDR R4, [R3, #0] ; R4 := inp.Available
  185. STR R4, [FP, #available] ; available := R4
  186. END;
  187. ReleaseResource;
  188. (*p := SYSTEM.VAL(ADDRESS,inp);
  189. AcquireObject(p.lockAddr);
  190. available := SYSTEM.GET32(p.portAddr+InpAvailableOffset);
  191. ReleaseObject(p.lockAddr);*)
  192. RETURN available;
  193. END Available;
  194. (** Send data to an output port (blocking version) *)
  195. PROCEDURE Send*(out: Output; x: LONGINT);
  196. (*VAR p: POINTER {UNSAFE} TO PortDesc;*)
  197. BEGIN
  198. CODE
  199. LDR R3, [FP, #out] ; R3 := address of PortDesc.lockAddr
  200. LDR R1, [R3, #0] ; R1 := PortDesc.lockAddr
  201. END;
  202. AcquireResource;
  203. CODE
  204. LDR R2, [FP, #x] ; R2 := x
  205. LDR R3, [R3, #4] ; R3 := PortDesc.portAddr
  206. STR R2, [R3, #0] ; out.Data := R2
  207. END;
  208. ReleaseResource;
  209. (*p := SYSTEM.VAL(ADDRESS,out);
  210. AcquireObject(p.lockAddr);
  211. SYSTEM.PUT32(p.portAddr+OutDataOffset,x);
  212. ReleaseObject(p.lockAddr);*)
  213. END Send;
  214. (** Send data to an output port (non-blocking version) *)
  215. PROCEDURE SendNonBlocking*(out: Output; x: LONGINT): BOOLEAN;
  216. VAR b: BOOLEAN;
  217. (*VAR p: POINTER {UNSAFE} TO PortDesc;*)
  218. BEGIN
  219. CODE
  220. LDR R3, [FP, #out] ; R3 := address of PortDesc.lockAddr
  221. LDR R1, [R3, #0] ; R1 := PortDesc.lockAddr
  222. END;
  223. AcquireResource;
  224. CODE
  225. LDR R2, [FP, #x] ; R2 := x
  226. LDR R3, [R3, #4] ; R3 := PortDesc.portAddr
  227. LDR R4, [R3, #4] ; R4 := out.Ready
  228. STRB R4, [FP, #b] ; b := R4
  229. CMP R4, #0
  230. BEQ Exit
  231. STR R2, [R3, #0] ; out.Data := R2
  232. Exit:
  233. END;
  234. ReleaseResource;
  235. (*p := SYSTEM.VAL(ADDRESS,out);
  236. AcquireObject(p.lockAddr);
  237. b := SYSTEM.VAL(BOOLEAN,SYSTEM.GET32(p.portAddr+OutReadyOffset));
  238. IF b THEN SYSTEM.PUT32(p.portAddr+OutDataOffset,x); END;
  239. ReleaseObject(p.lockAddr);*)
  240. RETURN b;
  241. END SendNonBlocking;
  242. OPERATOR "<<"*(out: Output; x: LONGINT);
  243. BEGIN
  244. Send(out,x);
  245. END "<<";
  246. OPERATOR ">>"*(x: LONGINT; out: Output);
  247. BEGIN
  248. Send(out,x);
  249. END ">>";
  250. OPERATOR "<<?"*(out: Output; x: LONGINT): BOOLEAN;
  251. BEGIN
  252. RETURN SendNonBlocking(out,x);
  253. END "<<?";
  254. OPERATOR ">>?"*(x: LONGINT; out: Output): BOOLEAN;
  255. BEGIN
  256. RETURN SendNonBlocking(out,x);
  257. END ">>?";
  258. (** Receive data from an input port (blocking version) *)
  259. PROCEDURE Receive*(inp: Input; VAR x: LONGINT);
  260. (*VAR p: POINTER {UNSAFE} TO PortDesc;*)
  261. BEGIN
  262. CODE
  263. LDR R3, [FP, #inp] ; R3 := address of PortDesc.lockAddr
  264. LDR R1, [R3, #0] ; R1 := PortDesc.lockAddr
  265. END;
  266. AcquireResource;
  267. CODE
  268. LDR R2, [FP, #x] ; R2 := address of x
  269. LDR R3, [R3, #4] ; R3 := PortDesc.portAddr
  270. LDR R4, [R3, #8] ; R4 := inp.Data
  271. STR R4, [R2, #0] ; x := R4
  272. END;
  273. ReleaseResource;
  274. (*p := SYSTEM.VAL(ADDRESS,inp);
  275. AcquireObject(p.lockAddr);
  276. x := SYSTEM.GET32(p.portAddr+InpDataOffset);
  277. ReleaseObject(p.lockAddr);*)
  278. END Receive;
  279. (** Receive data from an input port (non-blocking version) *)
  280. PROCEDURE ReceiveNonBlocking*(inp: Input; VAR x: LONGINT): BOOLEAN;
  281. VAR b: BOOLEAN;
  282. (*VAR p: POINTER {UNSAFE} TO PortDesc;*)
  283. BEGIN
  284. CODE
  285. LDR R3, [FP, #inp] ; R3 := address of PortDesc.lockAddr
  286. LDR R1, [R3, #0] ; R1 := PortDesc.lockAddr
  287. END;
  288. AcquireResource;
  289. CODE
  290. LDR R3, [R3, #4] ; R3 := PortDesc.portAddr
  291. LDR R4, [R3, #0] ; R4 := inp.Available
  292. STRB R4, [FP, #b] ; b := R4
  293. CMP R4, #0
  294. BEQ Exit
  295. LDR R2, [FP, #x] ; R2 := address of x
  296. LDR R4, [R3, #8] ; R4 := inp.Data
  297. STR R4, [R2, #0] ; x := R4
  298. Exit:
  299. END;
  300. ReleaseResource;
  301. (*p := SYSTEM.VAL(ADDRESS,inp);
  302. AcquireObject(p.lockAddr);
  303. b := SYSTEM.VAL(BOOLEAN,SYSTEM.GET32(p.portAddr+InpAvailableOffset));
  304. IF b THEN x := SYSTEM.GET32(p.portAddr+InpDataOffset); END;
  305. ReleaseObject(p.lockAddr);*)
  306. RETURN b;
  307. END ReceiveNonBlocking;
  308. OPERATOR ">>"*(inp: Input; VAR x: LONGINT);
  309. BEGIN
  310. Receive(inp,x);
  311. END ">>";
  312. OPERATOR "<<"*(VAR x: LONGINT; inp: Input);
  313. BEGIN
  314. Receive(inp,x);
  315. END "<<";
  316. OPERATOR ">>?"*(inp: Input; VAR x: LONGINT): BOOLEAN;
  317. BEGIN
  318. RETURN ReceiveNonBlocking(inp,x);
  319. END ">>?";
  320. OPERATOR "<<?"*(VAR x: LONGINT; inp: Input): BOOLEAN;
  321. BEGIN
  322. RETURN ReceiveNonBlocking(inp,x);
  323. END "<<?";
  324. PROCEDURE SendMultiple(portAddr, dataAddr: ADDRESS; numElements: LONGINT);
  325. CODE
  326. LDR R0, [FP,#portAddr]
  327. LDR R1, [FP,#dataAddr]
  328. LDR R2, [FP,#numElements]
  329. CMP R2, #8
  330. BLT CheckLoop4
  331. Loop8: ; numElements >= 8, coalescing of 8 transfers
  332. LDR R3, [R1,#0]
  333. LDR R4, [R1,#4]
  334. LDR R5, [R1,#8]
  335. LDR R6, [R1,#12]
  336. LDR R7, [R1,#16]
  337. LDR R8, [R1,#20]
  338. LDR R9, [R1,#24]
  339. LDR R10, [R1,#28]
  340. STR R3, [R0,#0]
  341. STR R4, [R0,#0]
  342. STR R5, [R0,#0]
  343. STR R6, [R0,#0]
  344. STR R7, [R0,#0]
  345. STR R8, [R0,#0]
  346. STR R9, [R0,#0]
  347. STR R10, [R0,#0]
  348. ADD R1, R1, #32
  349. SUBS R2, R2, #8
  350. BGT Loop8
  351. CheckLoop4:
  352. CMP R2, #4
  353. BLT CheckLoop1
  354. Loop4: ; numElements >= 4, coalescing of 4 transfers
  355. LDR R3, [R1,#0]
  356. LDR R4, [R1,#4]
  357. LDR R5, [R1,#8]
  358. LDR R6, [R1,#12]
  359. STR R3, [R0,#0]
  360. STR R4, [R0,#0]
  361. STR R5, [R0,#0]
  362. STR R6, [R0,#0]
  363. ADD R1, R1, #16
  364. SUBS R2, R2, #4
  365. BGT Loop4
  366. CheckLoop1:
  367. CMP R2, #1
  368. BLT Exit
  369. Loop1: ; numElements >= 1, transfer element by element
  370. LDR R3, [R1,#0]
  371. STR R3, [R0,#0]
  372. ADD R1, R1, #4
  373. SUBS R2, R2, #1
  374. BGT Loop1
  375. Exit:
  376. END SendMultiple;
  377. PROCEDURE ReceiveMultiple(portAddr, dataAddr: ADDRESS; numElements: LONGINT);
  378. CODE
  379. LDR R0, [FP,#portAddr]
  380. ADD R0, R0, #8
  381. LDR R1, [FP,#dataAddr]
  382. LDR R2, [FP,#numElements]
  383. CMP R2, #8
  384. BLT CheckLoop4
  385. Loop8: ; numElements >= 8, coalescing of 8 transfers
  386. LDR R3, [R0,#0]
  387. LDR R4, [R0,#0]
  388. LDR R5, [R0,#0]
  389. LDR R6, [R0,#0]
  390. LDR R7, [R0,#0]
  391. LDR R8, [R0,#0]
  392. LDR R9, [R0,#0]
  393. LDR R10, [R0,#0]
  394. STR R3, [R1,#0]
  395. STR R4, [R1,#4]
  396. STR R5, [R1,#8]
  397. STR R6, [R1,#12]
  398. STR R7, [R1,#16]
  399. STR R8, [R1,#20]
  400. STR R9, [R1,#24]
  401. STR R10, [R1,#28]
  402. ADD R1, R1, #32
  403. SUBS R2, R2, #8
  404. BGT Loop8
  405. CheckLoop4:
  406. CMP R2, #4
  407. BLT CheckLoop1
  408. Loop4: ; numElements >= 4, coalescing of 4 transfers
  409. LDR R3, [R0,#0]
  410. LDR R4, [R0,#0]
  411. LDR R5, [R0,#0]
  412. LDR R6, [R0,#0]
  413. STR R3, [R1,#0]
  414. STR R4, [R1,#4]
  415. STR R5, [R1,#8]
  416. STR R6, [R1,#12]
  417. ADD R1, R1, #16
  418. SUBS R2, R2, #4
  419. BGT Loop4
  420. CheckLoop1:
  421. CMP R2, #1
  422. BLT Exit
  423. Loop1: ; numElements >= 1, transfer element by element
  424. LDR R3, [R0,#0]
  425. STR R3, [R1,#0]
  426. ADD R1, R1, #4
  427. SUBS R2, R2, #1
  428. BGT Loop1
  429. Exit:
  430. END ReceiveMultiple;
  431. OPERATOR "<<"*(port: Output; x: SET); BEGIN Send(port,SYSTEM.VAL(LONGINT,x)); END "<<";
  432. OPERATOR ">>"*(x: SET; port: Output); BEGIN Send(port,SYSTEM.VAL(LONGINT,x)); END ">>";
  433. OPERATOR "<<?"*(port: Output; x: SET): BOOLEAN; BEGIN RETURN SendNonBlocking(port,SYSTEM.VAL(LONGINT,x)); END "<<?";
  434. OPERATOR ">>?"*(x: SET; port: Output): BOOLEAN; BEGIN RETURN SendNonBlocking(port,SYSTEM.VAL(LONGINT,x)); END ">>?";
  435. OPERATOR ">>"*(port: Input; VAR x: SET); BEGIN Receive(port,SYSTEM.VAL(LONGINT,x)); END ">>";
  436. OPERATOR "<<"*(VAR x: SET; port: Input); BEGIN Receive(port,SYSTEM.VAL(LONGINT,x)); END "<<";
  437. OPERATOR ">>?"*(port: Input; VAR x: SET): BOOLEAN; BEGIN RETURN ReceiveNonBlocking(port,SYSTEM.VAL(LONGINT,x)); END ">>?";
  438. OPERATOR "<<?"*(VAR x: SET; port: Input): BOOLEAN; BEGIN RETURN ReceiveNonBlocking(port,SYSTEM.VAL(LONGINT,x)); END "<<?";
  439. OPERATOR "<<"*(port: Output; x: REAL); BEGIN Send(port,SYSTEM.VAL(LONGINT,x)); END "<<";
  440. OPERATOR ">>"*(x: REAL; port: Output); BEGIN Send(port,SYSTEM.VAL(LONGINT,x)); END ">>";
  441. OPERATOR "<<?"*(port: Output; x: REAL): BOOLEAN; BEGIN RETURN SendNonBlocking(port,SYSTEM.VAL(LONGINT,x)); END "<<?";
  442. OPERATOR ">>?"*(x: REAL; port: Output): BOOLEAN; BEGIN RETURN SendNonBlocking(port,SYSTEM.VAL(LONGINT,x)); END ">>?";
  443. OPERATOR ">>"*(port: Input; VAR x: REAL); BEGIN Receive(port,SYSTEM.VAL(LONGINT,x)); END ">>";
  444. OPERATOR "<<"*(VAR x: REAL; port: Input); BEGIN Receive(port,SYSTEM.VAL(LONGINT,x)); END "<<";
  445. OPERATOR ">>?"*(port: Input; VAR x: REAL): BOOLEAN; BEGIN RETURN ReceiveNonBlocking(port,SYSTEM.VAL(LONGINT,x)); END ">>?";
  446. OPERATOR "<<?"*(VAR x: REAL; port: Input): BOOLEAN; BEGIN RETURN ReceiveNonBlocking(port,SYSTEM.VAL(LONGINT,x)); END "<<?";
  447. END AcAxisIo.