Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
E
EtherBone Core
Manage
Activity
Members
Labels
Plan
Issues
0
Issue boards
Milestones
Wiki
Code
Merge requests
0
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Deploy
Releases
Monitor
Incidents
Service Desk
Analyze
Value stream analytics
Contributor analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Projects
EtherBone Core
Commits
bf0931d9
Commit
bf0931d9
authored
13 years ago
by
Wesley W. Terpstra
Browse files
Options
Downloads
Patches
Plain Diff
Implement sub-word access
parent
44a79f80
No related merge requests found
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
api/format/master.c
+56
-20
56 additions, 20 deletions
api/format/master.c
api/format/slave.c
+79
-38
79 additions, 38 deletions
api/format/slave.c
with
135 additions
and
58 deletions
api/format/master.c
+
56
−
20
View file @
bf0931d9
...
...
@@ -35,6 +35,7 @@
#include
"../glue/cycle.h"
#include
"../glue/device.h"
#include
"../glue/socket.h"
#include
"../glue/widths.h"
#include
"../transport/transport.h"
#include
"../memory/memory.h"
#include
"format.h"
...
...
@@ -62,8 +63,7 @@ void eb_device_flush(eb_device_t devicep) {
struct
eb_response
*
response
;
eb_cycle_t
cyclep
,
nextp
,
prevp
;
eb_response_t
responsep
;
eb_width_t
biggest
,
data
,
width
;
eb_data_t
data_mask
;
eb_width_t
biggest
,
data
,
addr
,
width
;
eb_address_t
address_mask
;
uint8_t
buffer
[
sizeof
(
eb_max_align_t
)
*
(
255
+
255
+
1
+
1
)
+
8
];
/* big enough for worst-case record */
uint8_t
*
wptr
,
*
cptr
,
*
eob
;
...
...
@@ -78,15 +78,10 @@ void eb_device_flush(eb_device_t devicep) {
assert (eb_width_refined(width) != 0);
*/
/* Determine alignment and masking sets */
data_mask
=
((
eb_data_t
)
1
)
<<
(((
width
&
EB_DATAX
)
<<
3
)
-
1
);
data_mask
=
(
data_mask
-
1
)
<<
1
|
1
;
address_mask
=
((
eb_address_t
)
1
)
<<
(((
width
&
EB_ADDRX
)
>>
1
)
-
1
);
address_mask
=
(
address_mask
-
1
)
<<
1
|
1
;
/* Calculate alignment values */
data
=
width
&
EB_DATAX
;
biggest
=
(
width
>>
4
)
|
data
;
addr
=
width
>>
4
;
biggest
=
addr
|
data
;
alignment
=
2
;
alignment
+=
(
biggest
>=
EB_DATA32
)
*
2
;
alignment
+=
(
biggest
>=
EB_DATA64
)
*
4
;
...
...
@@ -95,6 +90,10 @@ void eb_device_flush(eb_device_t devicep) {
header_alignment
=
record_alignment
;
stride
=
data
;
/* Determine alignment and masking sets */
address_mask
=
~
(
eb_address_t
)
0
;
address_mask
>>=
(
sizeof
(
eb_address_t
)
-
addr
)
<<
3
;
/* Non-streaming sockets need a header */
mtu
=
eb_transports
[
transport
->
link_type
].
mtu
;
if
(
mtu
!=
0
)
{
...
...
@@ -124,6 +123,8 @@ void eb_device_flush(eb_device_t devicep) {
struct
eb_operation
*
scan
;
eb_operation_t
operationp
;
eb_operation_t
scanp
;
eb_width_t
width
;
eb_data_t
data_mask
;
int
needs_check
,
cycle_end
;
unsigned
int
ops
,
maxops
;
eb_status_t
reason
;
...
...
@@ -151,23 +152,37 @@ void eb_device_flush(eb_device_t devicep) {
reason
=
EB_OK
;
/* silence warning */
for
(
operationp
=
cycle
->
first
;
operationp
!=
EB_NULL
;
operationp
=
operation
->
next
)
{
operation
=
EB_OPERATION
(
operationp
);
/* Determine operation port width: max of possibilities <= data */
width
=
eb_width_refine
(
operation
->
width
&
(
data
-
1
+
data
));
if
(
width
==
0
)
{
reason
=
EB_WIDTH
;
break
;
}
/* Report what the operation width ended up to be */
operation
->
width
=
width
;
/* Is the address too big for a bus op? */
if
((
operation
->
flags
&
EB_OP_CFG_SPACE
)
==
0
&&
(
operation
->
address
&
address_mask
)
!=
operation
->
address
)
{
(
operation
->
address
&
(
address_mask
-
(
width
-
1
))
)
!=
operation
->
address
)
{
reason
=
EB_ADDRESS
;
break
;
}
/* Is the address too big for a cfg op? */
if
((
operation
->
flags
&
EB_OP_CFG_SPACE
)
!=
0
&&
(
operation
->
address
&
0xFFFFU
)
!=
operation
->
address
)
{
(
operation
->
address
&
(
0xFFFFU
-
(
width
-
1
))
)
!=
operation
->
address
)
{
reason
=
EB_ADDRESS
;
break
;
}
/* Is the data too big for the port? */
if
((
operation
->
flags
&
EB_OP_MASK
)
==
EB_OP_WRITE
&&
(
operation
->
write_value
&
data_mask
)
!=
operation
->
write_value
)
{
reason
=
EB_WIDTH
;
break
;
if
((
operation
->
flags
&
EB_OP_MASK
)
==
EB_OP_WRITE
)
{
data_mask
=
~
(
eb_data_t
)
0
;
data_mask
>>=
(
sizeof
(
eb_data_t
)
-
width
)
<<
3
;
if
((
operation
->
write_value
&
data_mask
)
!=
operation
->
write_value
)
{
reason
=
EB_WIDTH
;
break
;
}
}
}
if
(
operationp
!=
EB_NULL
)
{
...
...
@@ -214,7 +229,10 @@ void eb_device_flush(eb_device_t devicep) {
while
(
!
cycle_end
)
{
int
wcount
,
rcount
,
rxcount
,
total
,
length
,
fifo
;
eb_address_t
bwa
;
eb_data_t
wv
;
eb_operation_flags_t
rcfg
,
wcfg
;
eb_width_t
width
;
uint8_t
bus_alignment
;
scanp
=
operationp
;
...
...
@@ -226,18 +244,25 @@ void eb_device_flush(eb_device_t devicep) {
wcount
=
0
;
fifo
=
0
;
wcfg
=
0
;
width
=
EB_DATAX
;
bus_alignment
=
0
;
}
else
{
wcfg
=
scan
->
flags
&
EB_OP_CFG_SPACE
;
bwa
=
scan
->
address
;
scanp
=
scan
->
next
;
width
=
scan
->
width
;
bus_alignment
=
bwa
&
(
data
-
1
);
if
(
wcfg
==
0
)
++
ops
;
/* How many writes can we chain? must be either FIFO or sequential in same address space */
if
(
ops
>=
maxops
||
scanp
==
EB_NULL
||
((
scan
=
EB_OPERATION
(
scanp
))
->
flags
&
EB_OP_MASK
)
!=
EB_OP_WRITE
||
(
scan
->
flags
&
EB_OP_CFG_SPACE
)
!=
wcfg
)
{
(
scan
->
flags
&
EB_OP_CFG_SPACE
)
!=
wcfg
||
scan
->
width
!=
width
)
{
/* Only a single write */
fifo
=
0
;
wcount
=
1
;
...
...
@@ -254,6 +279,7 @@ void eb_device_flush(eb_device_t devicep) {
if
(
scan
->
address
!=
bwa
)
break
;
if
((
scan
->
flags
&
EB_OP_MASK
)
!=
EB_OP_WRITE
)
break
;
if
((
scan
->
flags
&
EB_OP_CFG_SPACE
)
!=
wcfg
)
break
;
if
(
scan
->
width
!=
width
)
break
;
if
(
wcount
>=
255
)
break
;
if
(
ops
>=
maxops
)
break
;
if
(
wcfg
==
0
)
++
ops
;
...
...
@@ -270,6 +296,7 @@ void eb_device_flush(eb_device_t devicep) {
if
(
scan
->
address
!=
(
bwa
+=
stride
))
break
;
if
((
scan
->
flags
&
EB_OP_MASK
)
!=
EB_OP_WRITE
)
break
;
if
((
scan
->
flags
&
EB_OP_CFG_SPACE
)
!=
wcfg
)
break
;
if
(
scan
->
width
!=
width
)
break
;
if
(
wcount
>=
255
)
break
;
if
(
ops
>=
maxops
)
break
;
if
(
wcfg
==
0
)
++
ops
;
...
...
@@ -287,12 +314,15 @@ void eb_device_flush(eb_device_t devicep) {
/* First pack writes into a record, if any */
if
(
ops
>=
maxops
||
scanp
==
EB_NULL
||
((
scan
=
EB_OPERATION
(
scanp
))
->
flags
&
EB_OP_MASK
)
==
EB_OP_WRITE
)
{
((
scan
=
EB_OPERATION
(
scanp
))
->
flags
&
EB_OP_MASK
)
==
EB_OP_WRITE
||
(
width
!=
EB_DATAX
&&
(
scan
->
width
!=
width
||
(
scan
->
address
&
(
data
-
1
))
!=
bus_alignment
)))
{
/* No reads in this record */
rcount
=
0
;
rcfg
=
0
;
}
else
{
rcfg
=
scan
->
flags
&
EB_OP_CFG_SPACE
;
width
=
scan
->
width
;
bus_alignment
=
scan
->
address
&
(
data
-
1
);
if
(
rcfg
==
0
)
++
ops
;
rcount
=
1
;
...
...
@@ -300,6 +330,8 @@ void eb_device_flush(eb_device_t devicep) {
scan
=
EB_OPERATION
(
scanp
);
if
((
scan
->
flags
&
EB_OP_MASK
)
==
EB_OP_WRITE
)
break
;
if
((
scan
->
flags
&
EB_OP_CFG_SPACE
)
!=
rcfg
)
break
;
if
(
scan
->
width
!=
width
)
break
;
if
((
scan
->
address
&
(
data
-
1
))
!=
bus_alignment
)
break
;
if
(
rcount
>=
255
)
break
;
if
(
ops
>=
maxops
)
break
;
if
(
rcfg
==
0
)
++
ops
;
...
...
@@ -307,8 +339,9 @@ void eb_device_flush(eb_device_t devicep) {
}
}
if
(
rcount
==
0
&&
(
ops
>=
maxops
||
(
scanp
==
EB_NULL
&&
needs_check
&&
ops
>
0
)))
{
if
(
rcount
==
0
&&
width
>=
data
&&
(
ops
>=
maxops
||
(
scanp
==
EB_NULL
&&
needs_check
&&
ops
>
0
)))
{
/* Insert error-flag read */
width
=
data
;
rxcount
=
1
;
rcfg
=
1
;
}
else
{
...
...
@@ -376,7 +409,7 @@ void eb_device_flush(eb_device_t devicep) {
(
wcfg
?
EB_RECORD_WCA
:
0
)
|
(
fifo
?
EB_RECORD_WFF
:
0
)
|
(
cycle_end
?
EB_RECORD_CYC
:
0
);
wptr
[
1
]
=
0
;
wptr
[
1
]
=
(
0xFF
>>
(
8
-
width
))
<<
bus_alignment
;
wptr
[
2
]
=
wcount
;
wptr
[
3
]
=
rxcount
;
wptr
+=
record_alignment
;
...
...
@@ -391,7 +424,10 @@ void eb_device_flush(eb_device_t devicep) {
for
(;
wcount
--
;
operationp
=
operation
->
next
)
{
operation
=
EB_OPERATION
(
operationp
);
EB_mWRITE
(
wptr
,
operation
->
write_value
,
alignment
);
wv
=
operation
->
write_value
;
wv
<<=
(
bus_alignment
<<
3
);
EB_mWRITE
(
wptr
,
wv
,
alignment
);
wptr
+=
alignment
;
}
}
...
...
This diff is collapsed.
Click to expand it.
api/format/slave.c
+
79
−
38
View file @
bf0931d9
...
...
@@ -55,6 +55,10 @@ static inline void EB_sWRITE(uint8_t* wptr, eb_data_t val, int alignment) {
}
}
/* Find the offset */
static
uint8_t
eb_log2_table
[
8
]
=
{
0
,
1
,
2
,
4
,
7
,
3
,
6
,
5
};
static
inline
uint8_t
eb_log2
(
uint8_t
x
)
{
return
eb_log2_table
[(
uint8_t
)(
x
*
0x17
)
>>
5
];
}
void
eb_device_slave
(
eb_socket_t
socketp
,
eb_transport_t
transportp
,
eb_device_t
devicep
)
{
struct
eb_socket
*
socket
;
struct
eb_transport
*
transport
;
...
...
@@ -65,11 +69,8 @@ void eb_device_slave(eb_socket_t socketp, eb_transport_t transportp, eb_device_t
uint8_t
buffer
[
sizeof
(
eb_max_align_t
)
*
(
255
+
255
+
1
+
1
)
+
8
];
/* big enough for worst-case record */
uint8_t
*
wptr
,
*
rptr
,
*
eos
;
uint64_t
error
;
eb_width_t
widths
,
biggest
,
data
;
#ifdef ANAL
eb_data_t
data_mask
;
eb_address_t
address_mask
;
#endif
eb_width_t
widths
,
biggest
,
data
,
addr
;
eb_address_t
address_check_bits
;
int
alignment
,
record_alignment
,
header_alignment
,
stride
,
cycle
;
int
reply
,
header
,
passive
,
active
;
...
...
@@ -84,7 +85,7 @@ void eb_device_slave(eb_socket_t socketp, eb_transport_t transportp, eb_device_t
link
=
EB_LINK
(
linkp
);
widths
=
device
->
widths
;
header
=
widths
==
0
;
header
=
widths
==
0
;
passive
=
device
->
passive
==
devicep
;
active
=
!
passive
;
...
...
@@ -166,17 +167,10 @@ void eb_device_slave(eb_socket_t socketp, eb_transport_t transportp, eb_device_t
if
(
!
eb_width_possible
(
widths
))
goto
kill
;
}
#ifdef ANAL
/* Determine alignment and masking sets */
data_mask
=
((
eb_data_t
)
1
)
<<
(((
widths
&
EB_DATAX
)
<<
3
)
-
1
);
data_mask
=
(
data_mask
-
1
)
<<
1
|
1
;
address_mask
=
((
eb_address_t
)
1
)
<<
(((
widths
&
EB_ADDRX
)
>>
1
)
-
1
);
address_mask
=
(
address_mask
-
1
)
<<
1
|
1
;
#endif
/* Alignment is either 2, 4, or 8. */
data
=
widths
&
EB_DATAX
;
biggest
=
(
widths
>>
4
)
|
data
;
addr
=
widths
>>
4
;
biggest
=
addr
|
data
;
alignment
=
2
;
alignment
+=
(
biggest
>=
EB_DATA32
)
*
2
;
alignment
+=
(
biggest
>=
EB_DATA64
)
*
4
;
...
...
@@ -186,6 +180,10 @@ void eb_device_slave(eb_socket_t socketp, eb_transport_t transportp, eb_device_t
/* FIFO stride size */
stride
=
data
;
address_check_bits
=
~
(
eb_address_t
)
0
;
address_check_bits
>>=
(
sizeof
(
eb_address_t
)
-
addr
)
<<
3
;
address_check_bits
=
~
address_check_bits
|
(
data
-
1
);
/* Setup the initial pointers */
wptr
=
&
buffer
[
0
];
if
(
header
)
wptr
+=
header_alignment
;
...
...
@@ -201,15 +199,43 @@ resume_cycle:
/* Start processing the payload */
while
(
rptr
<=
eos
-
record_alignment
)
{
int
total
,
wconfig
,
wfifo
,
rconfig
,
rfifo
,
bconfig
;
int
total
,
wconfig
,
wfifo
,
rconfig
,
rfifo
,
bconfig
,
addr_ok
,
sel_ok
;
eb_address_t
bwa
,
bra
,
ra
;
eb_data_t
wv
;
eb_data_t
wv
,
data_mask
;
eb_width_t
op_width
,
op_widths
;
uint8_t
op_shift
,
bits
,
bits1
;
uint8_t
flags
=
rptr
[
0
];
uint8_t
select
=
rptr
[
1
];
uint8_t
wcount
=
rptr
[
2
];
uint8_t
rcount
=
rptr
[
3
];
rptr
+=
record_alignment
;
/* Decode the intended width from the select lines */
/* Step 1. How many bytes shifted are the operations?
* op_shift = position of first set bit
*/
op_shift
=
eb_log2
(
select
&
-
select
);
/* Step 2. How many ones are there in a row? */
bits
=
select
>>
op_shift
;
bits1
=
(
bits
>>
1
)
+
1
;
op_widths
=
eb_log2
(
bits1
);
op_width
=
op_widths
+
1
;
/* Step 3. Check that the bitmask is valid */
sel_ok
=
select
!=
0
/* select is not 0 */
&&
(
bits
&
(
bits
+
1
))
==
0
/* One bit set => was an unbroken sequence of bits */
&&
(
op_width
&
op_widths
)
==
0
/* One bit set => operation length was a power of two */
&&
(
op_shift
&
op_widths
)
==
0
/* The operation is aligned to the width */
&&
op_width
<=
data
/* The width must be supported by the port */
&&
op_shift
<
data
;
/* The shift must be supported by the port */
/* Create a mask for filtering out the important write data */
data_mask
=
~
(
eb_data_t
)
0
;
data_mask
>>=
(
sizeof
(
eb_data_t
)
-
op_width
)
<<
3
;
/* Is the cycle flag high? */
cycle
=
flags
&
EB_RECORD_CYC
;
...
...
@@ -248,21 +274,26 @@ resume_cycle:
wconfig
=
flags
&
EB_RECORD_WCA
;
bwa
=
EB_LOAD
(
rptr
,
alignment
);
#ifdef ANAL
if
((
bwa
&
address_mask
)
!=
0
)
goto
fail
;
#endif
rptr
+=
alignment
;
addr_ok
=
sel_ok
&&
(
bwa
&
address_check_bits
)
==
(
eb_address_t
)
op_shift
;
while
(
wcount
--
)
{
wv
=
EB_LOAD
(
rptr
,
alignment
);
rptr
+=
alignment
;
#ifdef ANAL
if
((
wv
&
data_mask
)
!=
0
)
goto
fail
;
#endif
if
(
wconfig
)
eb_socket_write_config
(
socketp
,
widths
,
bwa
,
wv
);
else
eb_socket_write
(
socketp
,
widths
,
bwa
,
wv
,
&
error
);
wv
>>=
(
op_shift
<<
3
);
wv
&=
data_mask
;
if
(
wconfig
)
{
eb_socket_write_config
(
socketp
,
op_width
,
bwa
,
wv
);
}
else
{
if
(
addr_ok
)
eb_socket_write
(
socketp
,
op_width
,
bwa
,
wv
,
&
error
);
else
error
=
(
error
<<
1
)
|
1
;
}
if
(
wfifo
==
0
)
bwa
+=
stride
;
}
}
...
...
@@ -280,16 +311,13 @@ resume_cycle:
wptr
[
0
]
=
cycle
|
(
bconfig
?
EB_RECORD_WCA
:
0
)
|
(
rfifo
?
EB_RECORD_WFF
:
0
);
wptr
[
1
]
=
0
;
wptr
[
1
]
=
select
;
wptr
[
2
]
=
rcount
;
wptr
[
3
]
=
0
;
wptr
+=
record_alignment
;
bra
=
EB_LOAD
(
rptr
,
alignment
);
#ifdef ANAL
if
((
bra
&
address_mask
)
!=
0
)
goto
fail
;
#endif
rptr
+=
alignment
;
/* Echo back the base return address */
...
...
@@ -299,13 +327,26 @@ resume_cycle:
while
(
rcount
--
)
{
ra
=
EB_LOAD
(
rptr
,
alignment
);
rptr
+=
alignment
;
#ifdef ANAL
if
((
ra
&
address_mask
)
!=
0
)
goto
fail
;
#endif
if
(
rconfig
)
wv
=
eb_socket_read_config
(
socketp
,
widths
,
ra
,
error
);
else
wv
=
eb_socket_read
(
socketp
,
widths
,
ra
,
&
error
);
addr_ok
=
sel_ok
&&
(
ra
&
address_check_bits
)
==
(
eb_address_t
)
op_shift
;
if
(
rconfig
)
{
if
(
addr_ok
)
{
wv
=
eb_socket_read_config
(
socketp
,
op_width
,
ra
,
error
);
}
else
{
wv
=
0
;
}
}
else
{
if
(
addr_ok
)
{
wv
=
eb_socket_read
(
socketp
,
op_width
,
ra
,
&
error
);
}
else
{
wv
=
0
;
error
=
(
error
<<
1
)
|
1
;
}
}
wv
&=
data_mask
;
wv
<<=
(
op_shift
<<
3
);
EB_sWRITE
(
wptr
,
wv
,
alignment
);
wptr
+=
alignment
;
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment