diff --git a/api/Makefile b/api/Makefile index e0cf62c646219bbf70d034addd1c58081ee61d3e..aa405dafcfd43ee9d2d74448fba6c6a2528f299b 100644 --- a/api/Makefile +++ b/api/Makefile @@ -1,6 +1,9 @@ -BUILD = lm32 +# The installation prefix default to /usr/local, but can be set on the cmdline +PREFIX ?= /usr/local + +#BUILD = lm32 #BUILD = win32 -#BUILD = unix +BUILD = unix ifeq ($(BUILD), lm32) TARGET = lm32-elf- @@ -13,7 +16,7 @@ EXTRA = libetherbone.dll.a endif ifeq ($(BUILD), unix) FLAGS = -fPIC -LIBS = -Wl,-rpath,/usr/local/lib +LIBS = -Wl,-rpath,$(PREFIX)/lib LIBRARY = libetherbone.so EXTRA = libetherbone.so.* endif @@ -40,7 +43,7 @@ ARCHIVE = etherbone.a FLAGS := $(FLAGS) -Wall -O2 #FLAGS := $(FLAGS) -DEB_USE_DYNAMIC # deterministic untill table overflow (default) -FLAGS := $(FLAGS) -DEB_USE_STATIC=200 # fully deterministic +#FLAGS := $(FLAGS) -DEB_USE_STATIC=200 # fully deterministic #FLAGS := $(FLAGS) -DEB_USE_MALLOC # non-deterministic #FLAGS := $(FLAGS) -DDISABLE_SLAVE #FLAGS := $(FLAGS) -DDISABLE_MASTER @@ -72,9 +75,10 @@ SOURCES = memory/static.c \ all: glue/version.h $(TOOLS) $(TESTS) $(ARCHIVE) $(LIBRARY) install: all - cp -a $(LIBRARY) $(EXTRA) $(ARCHIVE) /usr/local/lib - cp -a etherbone.h /usr/local/include - cp -a $(TOOLS) /usr/local/bin + mkdir -p $(PREFIX)/bin $(PREFIX)/include $(PREFIX)/lib + cp -a $(LIBRARY) $(EXTRA) $(ARCHIVE) $(PREFIX)/lib + cp -a etherbone.h $(PREFIX)/include + cp -a $(TOOLS) $(PREFIX)/bin glue/version.h:: git log -n1 --pretty="format:%H" . > git.version_full diff --git a/api/etherbone.h b/api/etherbone.h index 18913f37cab86f13583278e6429f801080f939b7..ebf5e66621539066ebf08e19272ae1dac5fd6ea8 100644 --- a/api/etherbone.h +++ b/api/etherbone.h @@ -29,8 +29,6 @@ #ifndef ETHERBONE_H #define ETHERBONE_H -#define DEBUG_EB 1 - #define EB_PROTOCOL_VERSION 1 #define EB_ABI_VERSION 0x02 /* incremented on incompatible changes */ @@ -267,11 +265,6 @@ extern "C" { /* C99 API */ /****************************************************************************/ -extern int mprintf(char const *format, ...); - -#define dbgprint(fmt, ...) \ - do { if (DEBUG_EB) mprintf(fmt, ##__VA_ARGS__); } while (0) - /* Convert status to a human-readable printable string */ EB_PUBLIC const char* eb_status(eb_status_t code); @@ -613,7 +606,7 @@ class Socket { status_t attach(sdb_device_t device, Handler* handler); status_t detach(sdb_device_t device); - int run(int timeout_us); + int run(int timeout_us = -1); /* These can be used to implement your own 'block': */ uint32_t timeout() const; @@ -640,15 +633,24 @@ class Device { width_t width() const; + template <typename T> + status_t sdb_scan_bus (sdb_bridge_t bridge, T* user, sdb_callback_t); + template <typename T> + status_t sdb_scan_root(T* user, sdb_callback_t); + protected: Device(eb_device_t device); eb_device_t device; friend class Cycle; template <typename T, void (T::*cb)(Device, Operation, status_t)> - friend void wrap_member_callback(T* object, eb_device_t dev, eb_operation_t op, eb_status_t status); - template <typename T, void (*cb)(Device, Operation, status_t)> - friend void wrap_function_callback(T* user, eb_device_t dev, eb_operation_t op, eb_status_t status); + friend void wrap_member_callback(eb_user_data_t object, eb_device_t dev, eb_operation_t op, eb_status_t status); + template <typename T, void (*cb)(T*, Device, Operation, status_t)> + friend void wrap_function_callback(eb_user_data_t user, eb_device_t dev, eb_operation_t op, eb_status_t status); + template <typename T, void (T::*cb)(Device, sdb_t, status_t)> + friend void sdb_wrap_member_callback(eb_user_data_t user, eb_device_t dev, sdb_t sdb, eb_status_t status); + template <typename T, void (*cb)(T* user, Device, sdb_t, status_t)> + friend void sdb_wrap_function_callback(eb_user_data_t user, eb_device_t dev, sdb_t sdb, eb_status_t status); }; class Cycle { @@ -657,7 +659,7 @@ class Cycle { // Start a cycle on the target device. template <typename T> - status_t open(Device device, T* user, void (*cb)(T*, eb_device_t, eb_operation_t, eb_status_t)); + status_t open(Device device, T* user, eb_callback_t); status_t open(Device device); void abort(); @@ -700,19 +702,29 @@ class Operation { eb_operation_t operation; template <typename T, void (T::*cb)(Device, Operation, status_t)> - friend void wrap_member_callback(T* object, eb_device_t dev, eb_operation_t op, eb_status_t status); - template <typename T, void (*cb)(Device, Operation, status_t)> - friend void wrap_function_callback(T* user, eb_device_t dev, eb_operation_t op, eb_status_t status); + friend void wrap_member_callback(eb_user_data_t object, eb_device_t dev, eb_operation_t op, eb_status_t status); + template <typename T, void (*cb)(T*, Device, Operation, status_t)> + friend void wrap_function_callback(eb_user_data_t user, eb_device_t dev, eb_operation_t op, eb_status_t status); }; /* Convenience templates to convert member functions into callback type */ template <typename T, void (T::*cb)(Device, Operation, status_t)> -void wrap_member_callback(T* object, eb_device_t dev, eb_operation_t op, eb_status_t status) { - return (object->*cb)(Device(dev), Operation(op), status); +void wrap_member_callback(eb_user_data_t user, eb_device_t dev, eb_operation_t op, eb_status_t status) { + return (reinterpret_cast<T*>(user)->*cb)(Device(dev), Operation(op), status); } template <typename T, void (*cb)(T* user, Device, Operation, status_t)> -void wrap_function_callback(T* user, eb_device_t dev, eb_operation_t op, eb_status_t status) { - return (*cb)(user, Device(dev), Operation(op), status); +void wrap_function_callback(eb_user_data_t user, eb_device_t dev, eb_operation_t op, eb_status_t status) { + return (*cb)(reinterpret_cast<T*>(user), Device(dev), Operation(op), status); +} + +template <typename T, void (T::*cb)(Device, sdb_t, status_t)> +void sdb_wrap_member_callback(eb_user_data_t user, eb_device_t dev, sdb_t sdb, eb_status_t status) { + return (reinterpret_cast<T*>(user)->*cb)(Device(dev), sdb, status); +} + +template <typename T, void (*cb)(T* user, Device, sdb_t, status_t)> +void sdb_wrap_function_callback(eb_user_data_t user, eb_device_t dev, sdb_t sdb, eb_status_t status) { + return (*cb)(reinterpret_cast<T*>(user), Device(dev), sdb, status); } /****************************************************************************/ @@ -808,13 +820,23 @@ inline status_t Device::flush() { return eb_device_flush(device); } +template <typename T> +inline eb_status_t Device::sdb_scan_bus(sdb_bridge_t bridge, T* user, sdb_callback_t cb) { + return eb_sdb_scan_bus(device, bridge, user, cb); +} + +template <typename T> +inline eb_status_t Device::sdb_scan_root(T* user, sdb_callback_t cb) { + return eb_sdb_scan_root(device, user, cb); +} + inline Cycle::Cycle() : cycle(EB_NULL) { } template <typename T> -inline eb_status_t Cycle::open(Device device, T* user, void (*cb)(T*, eb_device_t, eb_operation_t, status_t)) { - return eb_cycle_open(device.device, user, reinterpret_cast<eb_callback_t>(cb), &cycle); +inline eb_status_t Cycle::open(Device device, T* user, eb_callback_t cb) { + return eb_cycle_open(device.device, user, cb, &cycle); } inline eb_status_t Cycle::open(Device device) { diff --git a/api/format/master.c b/api/format/master.c index 8a5bae3c0634e3e56270cf820435c04b17e395db..9ead282df338c47f0578fd303ba0a92d441a2f65 100644 --- a/api/format/master.c +++ b/api/format/master.c @@ -31,9 +31,7 @@ #define EB_NEED_BIGENDIAN_64 1 #include <string.h> -#include <unistd.h> -#include "../etherbone.h" #include "../glue/operation.h" #include "../glue/cycle.h" #include "../glue/device.h" @@ -57,9 +55,6 @@ static void EB_mWRITE(uint8_t* wptr, eb_data_t val, int alignment) { * Thus, the EB_<TYPE>(x) conversions appear late and near their use. */ eb_status_t eb_device_flush(eb_device_t devicep) { - - dbgprint("Entering eb_device_flush\n"); - struct eb_socket* socket; struct eb_socket_aux* aux; struct eb_device* device; @@ -74,14 +69,13 @@ eb_status_t eb_device_flush(eb_device_t devicep) { eb_format_t format, size, endian; eb_address_t address_mask; uint8_t buffer[sizeof(eb_max_align_t)*(255+255+1+1)+8]; /* big enough for worst-case record */ - dbgprint("Allocated 520 byte record buffer\n"); uint8_t * wptr, * cptr, * eob; int alignment, record_alignment, header_alignment, stride, mtu, readback, has_reads; device = EB_DEVICE(devicep); transport = EB_TRANSPORT(device->transport); width = device->widths; - dbgprint("Device and Transport created.\n"); + if (device->link == EB_NULL) return EB_FAIL; /* @@ -104,13 +98,11 @@ eb_status_t eb_device_flush(eb_device_t devicep) { /* Determine alignment and masking sets */ address_mask = ~(eb_address_t)0; address_mask >>= (sizeof(eb_address_t) - addr) << 3; - dbgprint("Alignment and mask calculated.\n"); - + /* Begin buffering */ tops = &eb_transports[transport->link_type]; link = EB_LINK(device->link); tops->send_buffer(transport, link, 1); - dbgprint("Begun buffering ...\n"); /* Non-streaming sockets need a header */ mtu = tops->mtu; @@ -126,28 +118,16 @@ eb_status_t eb_device_flush(eb_device_t devicep) { cptr = wptr = &buffer[0]; eob = &buffer[sizeof(buffer)]; } - dbgprint("Header...\n"); - dbgprint("EB_NULL: %d\n", EB_NULL); - + /* Invert the list of cycles */ prevp = EB_NULL; for (cyclep = device->un_link.ready; cyclep != EB_NULL; cyclep = nextp) { - dbgprint("Traversing cycle list...\n"); - dbgprint("Before inversion:\n"); - dbgprint("CycPtr: %d, PrevP: %d, NextP: %d\n", cyclep, prevp, nextp); - - cycle = EB_CYCLE(cyclep); nextp = cycle->un_link.next; cycle->un_link.next = prevp; prevp = cyclep; - - dbgprint("After inversion:\n"); - dbgprint("CycPtr: %d, PrevP: %d, NextP: %d\n", cyclep, prevp, nextp); - usleep(500000); } - dbgprint("Cycle List inverted.\n"); - + has_reads = 0; for (cyclep = prevp; cyclep != EB_NULL; cyclep = nextp) { struct eb_operation* operation; @@ -161,12 +141,10 @@ eb_status_t eb_device_flush(eb_device_t devicep) { cycle = EB_CYCLE(cyclep); nextp = cycle->un_link.next; - - + /* Record the device which answers */ cycle->un_link.device = devicep; - dbgprint("OOM check\n"); - + /* Deal with OOM cases */ if (cycle->un_ops.dead == cyclep) { if (cycle->callback) @@ -181,10 +159,9 @@ eb_status_t eb_device_flush(eb_device_t devicep) { (*cycle->callback)(cycle->user_data, cycle->un_link.device, EB_NULL, EB_OK); eb_free_cycle(cyclep); continue; - } -dbgprint("area 1\n"); + } - /* Are there out of range widths? */ + /* Are there out of range widths? */ reason = EB_OK; /* silence warning */ for (operationp = cycle->un_ops.first; operationp != EB_NULL; operationp = operation->next) { operation = EB_OPERATION(operationp); @@ -218,8 +195,7 @@ dbgprint("area 1\n"); reason = EB_ADDRESS; break; } - dbgprint("Area 2\n"); - + /* Is the address too big for a cfg op? */ if ((operation->flags & EB_OP_CFG_SPACE) != 0 && (operation->address & (0xFFFFU - (size - 1))) != operation->address) { @@ -257,7 +233,6 @@ dbgprint("area 1\n"); eb_free_cycle(cyclep); continue; } -dbgprint("Area 3\n"); /* Refresh pointers typically needed per cycle */ device = EB_DEVICE(devicep); @@ -275,8 +250,7 @@ dbgprint("Area 3\n"); } else { maxops = -1; } - dbgprint("Begin formatting\n"); - + /* Begin formatting the packet into records */ ops = 0; readback = 0; @@ -310,8 +284,7 @@ dbgprint("Area 3\n"); low_addr = bwa & (data-1); if (wcfg == 0) ++ops; - dbgprint("Area 4\n"); - + /* How many writes can we chain? must be either FIFO or sequential in same address space */ if (ops >= maxops || scanp == EB_NULL || @@ -364,7 +337,6 @@ dbgprint("Area 3\n"); } } } -dbgprint("Area 5\n"); /* Next, how many reads follow? */ /* First pack writes into a record, if any */ @@ -405,8 +377,7 @@ dbgprint("Area 5\n"); } else { rxcount = rcount; } - dbgprint("Area 6\n"); - + /* Compute total request length */ total = (wcount > 0) + wcount + (rxcount > 0) + rxcount; @@ -443,8 +414,7 @@ dbgprint("Area 5\n"); cptr = &buffer[header_alignment]; wptr = cptr + keep; } - dbgprint("Area 7\n"); - + /* Test for cycle overflow of MTU */ if (length > eob - wptr) { /* Blow up in the face of the user */ @@ -488,8 +458,7 @@ dbgprint("Area 5\n"); wptr[2] = wcount; wptr[3] = rxcount; wptr += record_alignment; - dbgprint("Area 8\n"); - + /* Fill in the writes */ if (wcount > 0) { operation = EB_OPERATION(operationp); @@ -537,8 +506,7 @@ dbgprint("Area 5\n"); } } } - dbgprint("Area 9\n"); - + /* Did we finish the while loop? */ if (cycle_end) { if (readback == 0) { @@ -569,8 +537,7 @@ dbgprint("Area 5\n"); cptr = wptr; } } - dbgprint("Area 10\n"); - + /* Refresh pointer derferences */ device = EB_DEVICE(devicep); transport = EB_TRANSPORT(device->transport); @@ -592,7 +559,6 @@ dbgprint("Area 5\n"); /* Clear the queue */ device->un_link.ready = EB_NULL; - dbgprint("Leaving eb_device_flush\n"); - + return EB_OK; } diff --git a/api/transport/lm32.c b/api/transport/lm32.c index f0f1727d35330404962685f49fdae5f32e8579e0..26cdf14118791c353b3669c304e1f593991d5297 100644 --- a/api/transport/lm32.c +++ b/api/transport/lm32.c @@ -35,6 +35,13 @@ #include "../etherbone.h" #include "lm32.h" +extern int mprintf(char const *format, ...); + +#define DEBUG_EB 1 + +#define dbgprint(fmt, ...) \ + do { if (DEBUG_EB) mprintf(fmt, ##__VA_ARGS__); } while (0) + #define IP_START 0 #define IP_VER_IHL 0 diff --git a/hdl/eb_slave_core/etherbone_pkg.vhd b/hdl/eb_slave_core/etherbone_pkg.vhd index 7a3e75f9b354de9cd06e9ab87b019f7ad985b8ba..1ed047b1fa08ae3a6bbeb98ba5ce127e6ccb9ff9 100644 --- a/hdl/eb_slave_core/etherbone_pkg.vhd +++ b/hdl/eb_slave_core/etherbone_pkg.vhd @@ -7,8 +7,24 @@ use work.wishbone_pkg.all; use work.wr_fabric_pkg.all; package etherbone_pkg is + constant c_etherbone_sdb : t_sdb_device := ( + abi_class => x"0000", -- undocumented device + abi_ver_major => x"01", + abi_ver_minor => x"01", + wbd_endian => c_sdb_endian_big, + wbd_width => x"4", --32-bit port granularity + sdb_component => ( + addr_first => x"0000000000000000", + addr_last => x"00000000000000ff", + product => ( + vendor_id => x"0000000000000651", -- GSI + device_id => x"68202b22", + version => x"00000001", + date => x"20130211", + name => "Etherbone-Config "))); + component eb_slave_core is -generic(g_sdb_address : std_logic_vector(63 downto 0)); + generic(g_sdb_address : std_logic_vector(63 downto 0)); port( clk_i : in std_logic; nRst_i : in std_logic;