123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523 |
- (**
- AUTHOR "Alexey Morozov, HighDim GmbH, 2015";
- PURPOSE "ActiveCells AXI4 Stream IO interface";
- *)
- MODULE AcAxisIo;
- IMPORT
- SYSTEM, Platform;
- CONST
- ChanOffset = 256*4; (* ActiveCells AXI4 Stream channel offset in bytes *)
- (*
- OutDataOffset = 0;
- OutReadyOffset = SIZEOF(LONGINT);
- InpAvailableOffset = 0;
- InpDataOffset = 2*SIZEOF(LONGINT);
- *)
- TYPE
- (* AXI4 Stream port descriptor *)
- PortDesc = RECORD
- lockAddr: ADDRESS; (** *)
- portAddr: ADDRESS;
- END;
- Output* = PORT OUT; (** AXI4 Stream output port *)
- Input* = PORT IN; (** AXI4 Stream input port *)
- VAR
- inputs: ARRAY 2 OF ARRAY 256 OF PortDesc;
- outputs: ARRAY 2 OF ARRAY 256 OF PortDesc;
- locks: ARRAY 2 OF LONGINT; (* locks for each physical channel *)
- (*
- (** AXI4 Stream output interface *)
- Output* = POINTER{UNSAFE,UNTRACED} TO RECORD
- data: LONGINT; (** output data, write only *)
- ready: BOOLEAN; (** TRUE when output is available for sending data *)
- padding: ARRAY 3 OF CHAR;
- END;
- (** AXI4 Stream input port description *)
- Input* = POINTER{UNSAFE,UNTRACED} TO RECORD
- available: BOOLEAN; (** TRUE when input data is available *)
- padding: ARRAY 7 OF CHAR;
- data: LONGINT; (** input data, read only *)
- END;
- *)
- (**
- Get AXI4 Stream input port
- physicalPortNum: physical port number
- logicalPortNum: logical port number
- *)
- PROCEDURE GetInput*(physicalPortNum, logicalPortNum: LONGINT; VAR port: Input): BOOLEAN;
- VAR
- portDesc: POINTER {UNSAFE} TO PortDesc;
- portAddr: ADDRESS;
- BEGIN
- CASE physicalPortNum OF
- |0: portAddr := Platform.MasterAxiGp0Base + logicalPortNum*ChanOffset;
- |1: portAddr := Platform.MasterAxiGp1Base + logicalPortNum*ChanOffset;
- ELSE
- RETURN FALSE;
- END;
- portDesc := ADDRESSOF(inputs[physicalPortNum,logicalPortNum]);
- portDesc.portAddr := portAddr;
- portDesc.lockAddr := ADDRESSOF(locks[physicalPortNum]);
- port := SYSTEM.VAL(Input,portDesc);
- RETURN TRUE;
- END GetInput;
- (**
- Get AXI4 Stream output port
- physicalPortNum: physical port number
- logicalPortNum: logical port number
- *)
- PROCEDURE GetOutput*(physicalPortNum, logicalPortNum: LONGINT; VAR port: Output): BOOLEAN;
- VAR
- portDesc: POINTER {UNSAFE} TO PortDesc;
- portAddr: ADDRESS;
- BEGIN
- CASE physicalPortNum OF
- |0: portAddr := Platform.MasterAxiGp0Base + logicalPortNum*ChanOffset;
- |1: portAddr := Platform.MasterAxiGp1Base + logicalPortNum*ChanOffset;
- ELSE
- RETURN FALSE;
- END;
- portDesc := ADDRESSOF(outputs[physicalPortNum,logicalPortNum]);
- portDesc.portAddr := portAddr;
- portDesc.lockAddr := ADDRESSOF(locks[physicalPortNum]);
- port := SYSTEM.VAL(Output,portDesc);
- RETURN TRUE;
- END GetOutput;
- (*
- Acquire exclusive access to a resource
- R1: lock address
- R0, R5 are used in addition
- Based on the code presented in "Barrier Litmus Tests and Cookbook" by Richard Grisenthwaite, ARM, 26.11.2009,
- *)
- PROCEDURE {NOPAF} -AcquireResource;
- CODE
- MOV R0, #1
- Loop:
- LDREX R5, R1 ; read lock
- CMP R5, #0 ; check if 0
- WFENE ; sleep if the lock is held
- STREXEQ R5, R0, R1 ; attempt to store new value
- CMPEQ R5, #0 ; test if store suceeded
- BNE Loop ; retry if not
- DMB ; ensures that all subsequent accesses are observed after the gaining of the lock is observed
-
- ; loads and stores in the critical region can now be performed
- END AcquireResource;
- (*
- Release exclusive access to a resource
- R1: lock address
- R0 is used in addition
- Based on the code presented in "Barrier Litmus Tests and Cookbook" by Richard Grisenthwaite, ARM, 26.11.2009,
- *)
- PROCEDURE {NOPAF} -ReleaseResource;
- CODE
- MOV R0, #0
- DMB ; ensure all previous accesses are observed before the lock is cleared
- STR R0, [R1, #0]
- ; clear the lock.
- DSB ; ensure completion of the store that cleared the lock before sending the event
- SEV
- END ReleaseResource;
- (*PROCEDURE AcquireObject(lockAddr: ADDRESS);
- BEGIN
- CODE
- LDR R1, [FP, #lockAddr] ; R1 := address of lock
- END;
- AcquireResource;
- END AcquireObject;
- PROCEDURE ReleaseObject(lockAddr: ADDRESS);
- BEGIN
- CODE
- LDR R1, [FP, #lockAddr] ; R1 := address of lock
- END;
- ReleaseResource
- END ReleaseObject;*)
- (**
- Returns TRUE if the given output port is ready to accept new data
- *)
- PROCEDURE Ready*(out: Output): BOOLEAN;
- VAR b: BOOLEAN;
- (*VAR p: POINTER {UNSAFE} TO PortDesc;*)
- BEGIN
- CODE
- LDR R3, [FP, #out] ; R3 := address of PortDesc.lockAddr
- LDR R1, [R3, #0] ; R1 := PortDesc.lockAddr
- END;
- AcquireResource;
- CODE
- LDR R3, [R3, #4] ; R3 := PortDesc.portAddr
- LDR R4, [R3, #4] ; R4 := out.Ready
- STRB R4, [FP, #b] ; b := R4
- END;
- ReleaseResource;
- (*p := SYSTEM.VAL(ADDRESS,out);
- AcquireObject(p.lockAddr);
- b := SYSTEM.VAL(BOOLEAN,SYSTEM.GET32(p.portAddr+OutReadyOffset));
- ReleaseObject(p.lockAddr);*)
- RETURN b;
- END Ready;
- (** Returns number of data elements available to read from an input port *)
- PROCEDURE Available*(inp: Input): LONGINT;
- VAR available: LONGINT;
- (*VAR p: POINTER {UNSAFE} TO PortDesc;*)
- BEGIN
- CODE
- LDR R3, [FP, #inp] ; R3 := address of PortDesc.lockAddr
- LDR R1, [R3, #0] ; R1 := PortDesc.lockAddr
- END;
- AcquireResource;
- CODE
- LDR R3, [R3, #4] ; R3 := PortDesc.portAddr
- LDR R4, [R3, #0] ; R4 := inp.Available
- STR R4, [FP, #available] ; available := R4
- END;
- ReleaseResource;
- (*p := SYSTEM.VAL(ADDRESS,inp);
- AcquireObject(p.lockAddr);
- available := SYSTEM.GET32(p.portAddr+InpAvailableOffset);
- ReleaseObject(p.lockAddr);*)
- RETURN available;
- END Available;
- (** Send data to an output port (blocking version) *)
- PROCEDURE Send*(out: Output; x: LONGINT);
- (*VAR p: POINTER {UNSAFE} TO PortDesc;*)
- BEGIN
- CODE
- LDR R3, [FP, #out] ; R3 := address of PortDesc.lockAddr
- LDR R1, [R3, #0] ; R1 := PortDesc.lockAddr
- END;
- AcquireResource;
- CODE
- LDR R2, [FP, #x] ; R2 := x
- LDR R3, [R3, #4] ; R3 := PortDesc.portAddr
- STR R2, [R3, #0] ; out.Data := R2
- END;
- ReleaseResource;
- (*p := SYSTEM.VAL(ADDRESS,out);
- AcquireObject(p.lockAddr);
- SYSTEM.PUT32(p.portAddr+OutDataOffset,x);
- ReleaseObject(p.lockAddr);*)
- END Send;
- (** Send data to an output port (non-blocking version) *)
- PROCEDURE SendNonBlocking*(out: Output; x: LONGINT): BOOLEAN;
- VAR b: BOOLEAN;
- (*VAR p: POINTER {UNSAFE} TO PortDesc;*)
- BEGIN
- CODE
- LDR R3, [FP, #out] ; R3 := address of PortDesc.lockAddr
- LDR R1, [R3, #0] ; R1 := PortDesc.lockAddr
- END;
- AcquireResource;
- CODE
- LDR R2, [FP, #x] ; R2 := x
- LDR R3, [R3, #4] ; R3 := PortDesc.portAddr
- LDR R4, [R3, #4] ; R4 := out.Ready
- STRB R4, [FP, #b] ; b := R4
- CMP R4, #0
- BEQ Exit
- STR R2, [R3, #0] ; out.Data := R2
- Exit:
- END;
- ReleaseResource;
- (*p := SYSTEM.VAL(ADDRESS,out);
- AcquireObject(p.lockAddr);
- b := SYSTEM.VAL(BOOLEAN,SYSTEM.GET32(p.portAddr+OutReadyOffset));
- IF b THEN SYSTEM.PUT32(p.portAddr+OutDataOffset,x); END;
- ReleaseObject(p.lockAddr);*)
- RETURN b;
- END SendNonBlocking;
- OPERATOR "<<"*(out: Output; x: LONGINT);
- BEGIN
- Send(out,x);
- END "<<";
- OPERATOR ">>"*(x: LONGINT; out: Output);
- BEGIN
- Send(out,x);
- END ">>";
- OPERATOR "<<?"*(out: Output; x: LONGINT): BOOLEAN;
- BEGIN
- RETURN SendNonBlocking(out,x);
- END "<<?";
- OPERATOR ">>?"*(x: LONGINT; out: Output): BOOLEAN;
- BEGIN
- RETURN SendNonBlocking(out,x);
- END ">>?";
- (** Receive data from an input port (blocking version) *)
- PROCEDURE Receive*(inp: Input; VAR x: LONGINT);
- (*VAR p: POINTER {UNSAFE} TO PortDesc;*)
- BEGIN
- CODE
- LDR R3, [FP, #inp] ; R3 := address of PortDesc.lockAddr
- LDR R1, [R3, #0] ; R1 := PortDesc.lockAddr
- END;
- AcquireResource;
- CODE
- LDR R2, [FP, #x] ; R2 := address of x
- LDR R3, [R3, #4] ; R3 := PortDesc.portAddr
- LDR R4, [R3, #8] ; R4 := inp.Data
- STR R4, [R2, #0] ; x := R4
- END;
- ReleaseResource;
- (*p := SYSTEM.VAL(ADDRESS,inp);
- AcquireObject(p.lockAddr);
- x := SYSTEM.GET32(p.portAddr+InpDataOffset);
- ReleaseObject(p.lockAddr);*)
- END Receive;
- (** Receive data from an input port (non-blocking version) *)
- PROCEDURE ReceiveNonBlocking*(inp: Input; VAR x: LONGINT): BOOLEAN;
- VAR b: BOOLEAN;
- (*VAR p: POINTER {UNSAFE} TO PortDesc;*)
- BEGIN
- CODE
- LDR R3, [FP, #inp] ; R3 := address of PortDesc.lockAddr
- LDR R1, [R3, #0] ; R1 := PortDesc.lockAddr
- END;
- AcquireResource;
- CODE
- LDR R3, [R3, #4] ; R3 := PortDesc.portAddr
- LDR R4, [R3, #0] ; R4 := inp.Available
- STRB R4, [FP, #b] ; b := R4
- CMP R4, #0
- BEQ Exit
- LDR R2, [FP, #x] ; R2 := address of x
- LDR R4, [R3, #8] ; R4 := inp.Data
- STR R4, [R2, #0] ; x := R4
- Exit:
- END;
- ReleaseResource;
- (*p := SYSTEM.VAL(ADDRESS,inp);
- AcquireObject(p.lockAddr);
- b := SYSTEM.VAL(BOOLEAN,SYSTEM.GET32(p.portAddr+InpAvailableOffset));
- IF b THEN x := SYSTEM.GET32(p.portAddr+InpDataOffset); END;
- ReleaseObject(p.lockAddr);*)
- RETURN b;
- END ReceiveNonBlocking;
- OPERATOR ">>"*(inp: Input; VAR x: LONGINT);
- BEGIN
- Receive(inp,x);
- END ">>";
- OPERATOR "<<"*(VAR x: LONGINT; inp: Input);
- BEGIN
- Receive(inp,x);
- END "<<";
- OPERATOR ">>?"*(inp: Input; VAR x: LONGINT): BOOLEAN;
- BEGIN
- RETURN ReceiveNonBlocking(inp,x);
- END ">>?";
- OPERATOR "<<?"*(VAR x: LONGINT; inp: Input): BOOLEAN;
- BEGIN
- RETURN ReceiveNonBlocking(inp,x);
- END "<<?";
- PROCEDURE SendMultiple(portAddr, dataAddr: ADDRESS; numElements: LONGINT);
- CODE
- LDR R0, [FP,#portAddr]
- LDR R1, [FP,#dataAddr]
- LDR R2, [FP,#numElements]
- CMP R2, #8
- BLT CheckLoop4
- Loop8: ; numElements >= 8, coalescing of 8 transfers
- LDR R3, [R1,#0]
- LDR R4, [R1,#4]
- LDR R5, [R1,#8]
- LDR R6, [R1,#12]
- LDR R7, [R1,#16]
- LDR R8, [R1,#20]
- LDR R9, [R1,#24]
- LDR R10, [R1,#28]
- STR R3, [R0,#0]
- STR R4, [R0,#0]
- STR R5, [R0,#0]
- STR R6, [R0,#0]
- STR R7, [R0,#0]
- STR R8, [R0,#0]
- STR R9, [R0,#0]
- STR R10, [R0,#0]
- ADD R1, R1, #32
- SUBS R2, R2, #8
- BGT Loop8
- CheckLoop4:
- CMP R2, #4
- BLT CheckLoop1
- Loop4: ; numElements >= 4, coalescing of 4 transfers
- LDR R3, [R1,#0]
- LDR R4, [R1,#4]
- LDR R5, [R1,#8]
- LDR R6, [R1,#12]
- STR R3, [R0,#0]
- STR R4, [R0,#0]
- STR R5, [R0,#0]
- STR R6, [R0,#0]
- ADD R1, R1, #16
- SUBS R2, R2, #4
- BGT Loop4
- CheckLoop1:
- CMP R2, #1
- BLT Exit
- Loop1: ; numElements >= 1, transfer element by element
- LDR R3, [R1,#0]
- STR R3, [R0,#0]
- ADD R1, R1, #4
- SUBS R2, R2, #1
- BGT Loop1
- Exit:
- END SendMultiple;
- PROCEDURE ReceiveMultiple(portAddr, dataAddr: ADDRESS; numElements: LONGINT);
- CODE
- LDR R0, [FP,#portAddr]
- ADD R0, R0, #8
- LDR R1, [FP,#dataAddr]
- LDR R2, [FP,#numElements]
- CMP R2, #8
- BLT CheckLoop4
- Loop8: ; numElements >= 8, coalescing of 8 transfers
- LDR R3, [R0,#0]
- LDR R4, [R0,#0]
- LDR R5, [R0,#0]
- LDR R6, [R0,#0]
- LDR R7, [R0,#0]
- LDR R8, [R0,#0]
- LDR R9, [R0,#0]
- LDR R10, [R0,#0]
- STR R3, [R1,#0]
- STR R4, [R1,#4]
- STR R5, [R1,#8]
- STR R6, [R1,#12]
- STR R7, [R1,#16]
- STR R8, [R1,#20]
- STR R9, [R1,#24]
- STR R10, [R1,#28]
- ADD R1, R1, #32
- SUBS R2, R2, #8
- BGT Loop8
- CheckLoop4:
- CMP R2, #4
- BLT CheckLoop1
- Loop4: ; numElements >= 4, coalescing of 4 transfers
- LDR R3, [R0,#0]
- LDR R4, [R0,#0]
- LDR R5, [R0,#0]
- LDR R6, [R0,#0]
- STR R3, [R1,#0]
- STR R4, [R1,#4]
- STR R5, [R1,#8]
- STR R6, [R1,#12]
- ADD R1, R1, #16
- SUBS R2, R2, #4
- BGT Loop4
- CheckLoop1:
- CMP R2, #1
- BLT Exit
- Loop1: ; numElements >= 1, transfer element by element
- LDR R3, [R0,#0]
- STR R3, [R1,#0]
- ADD R1, R1, #4
- SUBS R2, R2, #1
- BGT Loop1
- Exit:
- END ReceiveMultiple;
- OPERATOR "<<"*(port: Output; x: SET); BEGIN Send(port,SYSTEM.VAL(LONGINT,x)); END "<<";
- OPERATOR ">>"*(x: SET; port: Output); BEGIN Send(port,SYSTEM.VAL(LONGINT,x)); END ">>";
- OPERATOR "<<?"*(port: Output; x: SET): BOOLEAN; BEGIN RETURN SendNonBlocking(port,SYSTEM.VAL(LONGINT,x)); END "<<?";
- OPERATOR ">>?"*(x: SET; port: Output): BOOLEAN; BEGIN RETURN SendNonBlocking(port,SYSTEM.VAL(LONGINT,x)); END ">>?";
- OPERATOR ">>"*(port: Input; VAR x: SET); BEGIN Receive(port,SYSTEM.VAL(LONGINT,x)); END ">>";
- OPERATOR "<<"*(VAR x: SET; port: Input); BEGIN Receive(port,SYSTEM.VAL(LONGINT,x)); END "<<";
- OPERATOR ">>?"*(port: Input; VAR x: SET): BOOLEAN; BEGIN RETURN ReceiveNonBlocking(port,SYSTEM.VAL(LONGINT,x)); END ">>?";
- OPERATOR "<<?"*(VAR x: SET; port: Input): BOOLEAN; BEGIN RETURN ReceiveNonBlocking(port,SYSTEM.VAL(LONGINT,x)); END "<<?";
- OPERATOR "<<"*(port: Output; x: REAL); BEGIN Send(port,SYSTEM.VAL(LONGINT,x)); END "<<";
- OPERATOR ">>"*(x: REAL; port: Output); BEGIN Send(port,SYSTEM.VAL(LONGINT,x)); END ">>";
- OPERATOR "<<?"*(port: Output; x: REAL): BOOLEAN; BEGIN RETURN SendNonBlocking(port,SYSTEM.VAL(LONGINT,x)); END "<<?";
- OPERATOR ">>?"*(x: REAL; port: Output): BOOLEAN; BEGIN RETURN SendNonBlocking(port,SYSTEM.VAL(LONGINT,x)); END ">>?";
- OPERATOR ">>"*(port: Input; VAR x: REAL); BEGIN Receive(port,SYSTEM.VAL(LONGINT,x)); END ">>";
- OPERATOR "<<"*(VAR x: REAL; port: Input); BEGIN Receive(port,SYSTEM.VAL(LONGINT,x)); END "<<";
- OPERATOR ">>?"*(port: Input; VAR x: REAL): BOOLEAN; BEGIN RETURN ReceiveNonBlocking(port,SYSTEM.VAL(LONGINT,x)); END ">>?";
- OPERATOR "<<?"*(VAR x: REAL; port: Input): BOOLEAN; BEGIN RETURN ReceiveNonBlocking(port,SYSTEM.VAL(LONGINT,x)); END "<<?";
- END AcAxisIo.
|