Zynq.AcAxisIo.Mod 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523
  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. (*
  87. Acquire exclusive access to a resource
  88. R1: lock address
  89. R0, R5 are used in addition
  90. Based on the code presented in "Barrier Litmus Tests and Cookbook" by Richard Grisenthwaite, ARM, 26.11.2009,
  91. *)
  92. PROCEDURE {NOPAF} -AcquireResource;
  93. CODE
  94. MOV R0, #1
  95. Loop:
  96. LDREX R5, R1 ; read lock
  97. CMP R5, #0 ; check if 0
  98. WFENE ; sleep if the lock is held
  99. STREXEQ R5, R0, R1 ; attempt to store new value
  100. CMPEQ R5, #0 ; test if store suceeded
  101. BNE Loop ; retry if not
  102. DMB ; ensures that all subsequent accesses are observed after the gaining of the lock is observed
  103. ; loads and stores in the critical region can now be performed
  104. END AcquireResource;
  105. (*
  106. Release exclusive access to a resource
  107. R1: lock address
  108. R0 is used in addition
  109. Based on the code presented in "Barrier Litmus Tests and Cookbook" by Richard Grisenthwaite, ARM, 26.11.2009,
  110. *)
  111. PROCEDURE {NOPAF} -ReleaseResource;
  112. CODE
  113. MOV R0, #0
  114. DMB ; ensure all previous accesses are observed before the lock is cleared
  115. STR R0, [R1, #0]
  116. ; clear the lock.
  117. DSB ; ensure completion of the store that cleared the lock before sending the event
  118. SEV
  119. END ReleaseResource;
  120. (*PROCEDURE AcquireObject(lockAddr: ADDRESS);
  121. BEGIN
  122. CODE
  123. LDR R1, [FP, #lockAddr] ; R1 := address of lock
  124. END;
  125. AcquireResource;
  126. END AcquireObject;
  127. PROCEDURE ReleaseObject(lockAddr: ADDRESS);
  128. BEGIN
  129. CODE
  130. LDR R1, [FP, #lockAddr] ; R1 := address of lock
  131. END;
  132. ReleaseResource
  133. END ReleaseObject;*)
  134. (**
  135. Returns TRUE if the given output port is ready to accept new data
  136. *)
  137. PROCEDURE Ready*(out: Output): BOOLEAN;
  138. VAR b: BOOLEAN;
  139. (*VAR p: POINTER {UNSAFE} TO PortDesc;*)
  140. BEGIN
  141. CODE
  142. LDR R3, [FP, #out] ; R3 := address of PortDesc.lockAddr
  143. LDR R1, [R3, #0] ; R1 := PortDesc.lockAddr
  144. END;
  145. AcquireResource;
  146. CODE
  147. LDR R3, [R3, #4] ; R3 := PortDesc.portAddr
  148. LDR R4, [R3, #4] ; R4 := out.Ready
  149. STRB R4, [FP, #b] ; b := R4
  150. END;
  151. ReleaseResource;
  152. (*p := SYSTEM.VAL(ADDRESS,out);
  153. AcquireObject(p.lockAddr);
  154. b := SYSTEM.VAL(BOOLEAN,SYSTEM.GET32(p.portAddr+OutReadyOffset));
  155. ReleaseObject(p.lockAddr);*)
  156. RETURN b;
  157. END Ready;
  158. (** Returns number of data elements available to read from an input port *)
  159. PROCEDURE Available*(inp: Input): LONGINT;
  160. VAR available: LONGINT;
  161. (*VAR p: POINTER {UNSAFE} TO PortDesc;*)
  162. BEGIN
  163. CODE
  164. LDR R3, [FP, #inp] ; R3 := address of PortDesc.lockAddr
  165. LDR R1, [R3, #0] ; R1 := PortDesc.lockAddr
  166. END;
  167. AcquireResource;
  168. CODE
  169. LDR R3, [R3, #4] ; R3 := PortDesc.portAddr
  170. LDR R4, [R3, #0] ; R4 := inp.Available
  171. STR R4, [FP, #available] ; available := R4
  172. END;
  173. ReleaseResource;
  174. (*p := SYSTEM.VAL(ADDRESS,inp);
  175. AcquireObject(p.lockAddr);
  176. available := SYSTEM.GET32(p.portAddr+InpAvailableOffset);
  177. ReleaseObject(p.lockAddr);*)
  178. RETURN available;
  179. END Available;
  180. (** Send data to an output port (blocking version) *)
  181. PROCEDURE Send*(out: Output; x: LONGINT);
  182. (*VAR p: POINTER {UNSAFE} TO PortDesc;*)
  183. BEGIN
  184. CODE
  185. LDR R3, [FP, #out] ; R3 := address of PortDesc.lockAddr
  186. LDR R1, [R3, #0] ; R1 := PortDesc.lockAddr
  187. END;
  188. AcquireResource;
  189. CODE
  190. LDR R2, [FP, #x] ; R2 := x
  191. LDR R3, [R3, #4] ; R3 := PortDesc.portAddr
  192. STR R2, [R3, #0] ; out.Data := R2
  193. END;
  194. ReleaseResource;
  195. (*p := SYSTEM.VAL(ADDRESS,out);
  196. AcquireObject(p.lockAddr);
  197. SYSTEM.PUT32(p.portAddr+OutDataOffset,x);
  198. ReleaseObject(p.lockAddr);*)
  199. END Send;
  200. (** Send data to an output port (non-blocking version) *)
  201. PROCEDURE SendNonBlocking*(out: Output; x: LONGINT): BOOLEAN;
  202. VAR b: BOOLEAN;
  203. (*VAR p: POINTER {UNSAFE} TO PortDesc;*)
  204. BEGIN
  205. CODE
  206. LDR R3, [FP, #out] ; R3 := address of PortDesc.lockAddr
  207. LDR R1, [R3, #0] ; R1 := PortDesc.lockAddr
  208. END;
  209. AcquireResource;
  210. CODE
  211. LDR R2, [FP, #x] ; R2 := x
  212. LDR R3, [R3, #4] ; R3 := PortDesc.portAddr
  213. LDR R4, [R3, #4] ; R4 := out.Ready
  214. STRB R4, [FP, #b] ; b := R4
  215. CMP R4, #0
  216. BEQ Exit
  217. STR R2, [R3, #0] ; out.Data := R2
  218. Exit:
  219. END;
  220. ReleaseResource;
  221. (*p := SYSTEM.VAL(ADDRESS,out);
  222. AcquireObject(p.lockAddr);
  223. b := SYSTEM.VAL(BOOLEAN,SYSTEM.GET32(p.portAddr+OutReadyOffset));
  224. IF b THEN SYSTEM.PUT32(p.portAddr+OutDataOffset,x); END;
  225. ReleaseObject(p.lockAddr);*)
  226. RETURN b;
  227. END SendNonBlocking;
  228. OPERATOR "<<"*(out: Output; x: LONGINT);
  229. BEGIN
  230. Send(out,x);
  231. END "<<";
  232. OPERATOR ">>"*(x: LONGINT; out: Output);
  233. BEGIN
  234. Send(out,x);
  235. END ">>";
  236. OPERATOR "<<?"*(out: Output; x: LONGINT): BOOLEAN;
  237. BEGIN
  238. RETURN SendNonBlocking(out,x);
  239. END "<<?";
  240. OPERATOR ">>?"*(x: LONGINT; out: Output): BOOLEAN;
  241. BEGIN
  242. RETURN SendNonBlocking(out,x);
  243. END ">>?";
  244. (** Receive data from an input port (blocking version) *)
  245. PROCEDURE Receive*(inp: Input; VAR x: LONGINT);
  246. (*VAR p: POINTER {UNSAFE} TO PortDesc;*)
  247. BEGIN
  248. CODE
  249. LDR R3, [FP, #inp] ; R3 := address of PortDesc.lockAddr
  250. LDR R1, [R3, #0] ; R1 := PortDesc.lockAddr
  251. END;
  252. AcquireResource;
  253. CODE
  254. LDR R2, [FP, #x] ; R2 := address of x
  255. LDR R3, [R3, #4] ; R3 := PortDesc.portAddr
  256. LDR R4, [R3, #8] ; R4 := inp.Data
  257. STR R4, [R2, #0] ; x := R4
  258. END;
  259. ReleaseResource;
  260. (*p := SYSTEM.VAL(ADDRESS,inp);
  261. AcquireObject(p.lockAddr);
  262. x := SYSTEM.GET32(p.portAddr+InpDataOffset);
  263. ReleaseObject(p.lockAddr);*)
  264. END Receive;
  265. (** Receive data from an input port (non-blocking version) *)
  266. PROCEDURE ReceiveNonBlocking*(inp: Input; VAR x: LONGINT): BOOLEAN;
  267. VAR b: BOOLEAN;
  268. (*VAR p: POINTER {UNSAFE} TO PortDesc;*)
  269. BEGIN
  270. CODE
  271. LDR R3, [FP, #inp] ; R3 := address of PortDesc.lockAddr
  272. LDR R1, [R3, #0] ; R1 := PortDesc.lockAddr
  273. END;
  274. AcquireResource;
  275. CODE
  276. LDR R3, [R3, #4] ; R3 := PortDesc.portAddr
  277. LDR R4, [R3, #0] ; R4 := inp.Available
  278. STRB R4, [FP, #b] ; b := R4
  279. CMP R4, #0
  280. BEQ Exit
  281. LDR R2, [FP, #x] ; R2 := address of x
  282. LDR R4, [R3, #8] ; R4 := inp.Data
  283. STR R4, [R2, #0] ; x := R4
  284. Exit:
  285. END;
  286. ReleaseResource;
  287. (*p := SYSTEM.VAL(ADDRESS,inp);
  288. AcquireObject(p.lockAddr);
  289. b := SYSTEM.VAL(BOOLEAN,SYSTEM.GET32(p.portAddr+InpAvailableOffset));
  290. IF b THEN x := SYSTEM.GET32(p.portAddr+InpDataOffset); END;
  291. ReleaseObject(p.lockAddr);*)
  292. RETURN b;
  293. END ReceiveNonBlocking;
  294. OPERATOR ">>"*(inp: Input; VAR x: LONGINT);
  295. BEGIN
  296. Receive(inp,x);
  297. END ">>";
  298. OPERATOR "<<"*(VAR x: LONGINT; inp: Input);
  299. BEGIN
  300. Receive(inp,x);
  301. END "<<";
  302. OPERATOR ">>?"*(inp: Input; VAR x: LONGINT): BOOLEAN;
  303. BEGIN
  304. RETURN ReceiveNonBlocking(inp,x);
  305. END ">>?";
  306. OPERATOR "<<?"*(VAR x: LONGINT; inp: Input): BOOLEAN;
  307. BEGIN
  308. RETURN ReceiveNonBlocking(inp,x);
  309. END "<<?";
  310. PROCEDURE SendMultiple(portAddr, dataAddr: ADDRESS; numElements: LONGINT);
  311. CODE
  312. LDR R0, [FP,#portAddr]
  313. LDR R1, [FP,#dataAddr]
  314. LDR R2, [FP,#numElements]
  315. CMP R2, #8
  316. BLT CheckLoop4
  317. Loop8: ; numElements >= 8, coalescing of 8 transfers
  318. LDR R3, [R1,#0]
  319. LDR R4, [R1,#4]
  320. LDR R5, [R1,#8]
  321. LDR R6, [R1,#12]
  322. LDR R7, [R1,#16]
  323. LDR R8, [R1,#20]
  324. LDR R9, [R1,#24]
  325. LDR R10, [R1,#28]
  326. STR R3, [R0,#0]
  327. STR R4, [R0,#0]
  328. STR R5, [R0,#0]
  329. STR R6, [R0,#0]
  330. STR R7, [R0,#0]
  331. STR R8, [R0,#0]
  332. STR R9, [R0,#0]
  333. STR R10, [R0,#0]
  334. ADD R1, R1, #32
  335. SUBS R2, R2, #8
  336. BGT Loop8
  337. CheckLoop4:
  338. CMP R2, #4
  339. BLT CheckLoop1
  340. Loop4: ; numElements >= 4, coalescing of 4 transfers
  341. LDR R3, [R1,#0]
  342. LDR R4, [R1,#4]
  343. LDR R5, [R1,#8]
  344. LDR R6, [R1,#12]
  345. STR R3, [R0,#0]
  346. STR R4, [R0,#0]
  347. STR R5, [R0,#0]
  348. STR R6, [R0,#0]
  349. ADD R1, R1, #16
  350. SUBS R2, R2, #4
  351. BGT Loop4
  352. CheckLoop1:
  353. CMP R2, #1
  354. BLT Exit
  355. Loop1: ; numElements >= 1, transfer element by element
  356. LDR R3, [R1,#0]
  357. STR R3, [R0,#0]
  358. ADD R1, R1, #4
  359. SUBS R2, R2, #1
  360. BGT Loop1
  361. Exit:
  362. END SendMultiple;
  363. PROCEDURE ReceiveMultiple(portAddr, dataAddr: ADDRESS; numElements: LONGINT);
  364. CODE
  365. LDR R0, [FP,#portAddr]
  366. ADD R0, R0, #8
  367. LDR R1, [FP,#dataAddr]
  368. LDR R2, [FP,#numElements]
  369. CMP R2, #8
  370. BLT CheckLoop4
  371. Loop8: ; numElements >= 8, coalescing of 8 transfers
  372. LDR R3, [R0,#0]
  373. LDR R4, [R0,#0]
  374. LDR R5, [R0,#0]
  375. LDR R6, [R0,#0]
  376. LDR R7, [R0,#0]
  377. LDR R8, [R0,#0]
  378. LDR R9, [R0,#0]
  379. LDR R10, [R0,#0]
  380. STR R3, [R1,#0]
  381. STR R4, [R1,#4]
  382. STR R5, [R1,#8]
  383. STR R6, [R1,#12]
  384. STR R7, [R1,#16]
  385. STR R8, [R1,#20]
  386. STR R9, [R1,#24]
  387. STR R10, [R1,#28]
  388. ADD R1, R1, #32
  389. SUBS R2, R2, #8
  390. BGT Loop8
  391. CheckLoop4:
  392. CMP R2, #4
  393. BLT CheckLoop1
  394. Loop4: ; numElements >= 4, coalescing of 4 transfers
  395. LDR R3, [R0,#0]
  396. LDR R4, [R0,#0]
  397. LDR R5, [R0,#0]
  398. LDR R6, [R0,#0]
  399. STR R3, [R1,#0]
  400. STR R4, [R1,#4]
  401. STR R5, [R1,#8]
  402. STR R6, [R1,#12]
  403. ADD R1, R1, #16
  404. SUBS R2, R2, #4
  405. BGT Loop4
  406. CheckLoop1:
  407. CMP R2, #1
  408. BLT Exit
  409. Loop1: ; numElements >= 1, transfer element by element
  410. LDR R3, [R0,#0]
  411. STR R3, [R1,#0]
  412. ADD R1, R1, #4
  413. SUBS R2, R2, #1
  414. BGT Loop1
  415. Exit:
  416. END ReceiveMultiple;
  417. OPERATOR "<<"*(port: Output; x: SET); BEGIN Send(port,SYSTEM.VAL(LONGINT,x)); END "<<";
  418. OPERATOR ">>"*(x: SET; port: Output); BEGIN Send(port,SYSTEM.VAL(LONGINT,x)); END ">>";
  419. OPERATOR "<<?"*(port: Output; x: SET): BOOLEAN; BEGIN RETURN SendNonBlocking(port,SYSTEM.VAL(LONGINT,x)); END "<<?";
  420. OPERATOR ">>?"*(x: SET; port: Output): BOOLEAN; BEGIN RETURN SendNonBlocking(port,SYSTEM.VAL(LONGINT,x)); END ">>?";
  421. OPERATOR ">>"*(port: Input; VAR x: SET); BEGIN Receive(port,SYSTEM.VAL(LONGINT,x)); END ">>";
  422. OPERATOR "<<"*(VAR x: SET; port: Input); BEGIN Receive(port,SYSTEM.VAL(LONGINT,x)); END "<<";
  423. OPERATOR ">>?"*(port: Input; VAR x: SET): BOOLEAN; BEGIN RETURN ReceiveNonBlocking(port,SYSTEM.VAL(LONGINT,x)); END ">>?";
  424. OPERATOR "<<?"*(VAR x: SET; port: Input): BOOLEAN; BEGIN RETURN ReceiveNonBlocking(port,SYSTEM.VAL(LONGINT,x)); END "<<?";
  425. OPERATOR "<<"*(port: Output; x: REAL); BEGIN Send(port,SYSTEM.VAL(LONGINT,x)); END "<<";
  426. OPERATOR ">>"*(x: REAL; port: Output); BEGIN Send(port,SYSTEM.VAL(LONGINT,x)); END ">>";
  427. OPERATOR "<<?"*(port: Output; x: REAL): BOOLEAN; BEGIN RETURN SendNonBlocking(port,SYSTEM.VAL(LONGINT,x)); END "<<?";
  428. OPERATOR ">>?"*(x: REAL; port: Output): BOOLEAN; BEGIN RETURN SendNonBlocking(port,SYSTEM.VAL(LONGINT,x)); END ">>?";
  429. OPERATOR ">>"*(port: Input; VAR x: REAL); BEGIN Receive(port,SYSTEM.VAL(LONGINT,x)); END ">>";
  430. OPERATOR "<<"*(VAR x: REAL; port: Input); BEGIN Receive(port,SYSTEM.VAL(LONGINT,x)); END "<<";
  431. OPERATOR ">>?"*(port: Input; VAR x: REAL): BOOLEAN; BEGIN RETURN ReceiveNonBlocking(port,SYSTEM.VAL(LONGINT,x)); END ">>?";
  432. OPERATOR "<<?"*(VAR x: REAL; port: Input): BOOLEAN; BEGIN RETURN ReceiveNonBlocking(port,SYSTEM.VAL(LONGINT,x)); END "<<?";
  433. END AcAxisIo.