diff options
Diffstat (limited to 'tb/avalon.impl.hpp')
| -rw-r--r-- | tb/avalon.impl.hpp | 62 |
1 files changed, 62 insertions, 0 deletions
diff --git a/tb/avalon.impl.hpp b/tb/avalon.impl.hpp new file mode 100644 index 0000000..7f589ae --- /dev/null +++ b/tb/avalon.impl.hpp @@ -0,0 +1,62 @@ +#ifndef AVALON_IMPL_HPP +#define AVALON_IMPL_HPP + +#include <cassert> +#include <cstdio> + +namespace taller::avalon +{ + template<class Platform> + void interconnect<Platform>::attach(slave &dev) + { + devices.push_back(binding { dev.base_address(), dev.address_mask(), dev }); + } + + template<class Platform> + void interconnect<Platform>::tick() + { + auto addr = plat.avl_address; + if(!active) + { + if(addr & 0b11) + { + fprintf(stderr, "[avl] unaligned address: 0x%08x\n", addr); + assert(false); + } + + for(auto &binding : devices) + { + if((addr & binding.mask) == binding.base) + { + active = &binding.dev; + break; + } + } + + if(!active) + { + const char *op = plat.avl_read ? "read" : "write"; + fprintf(stderr, "[avl] attempt to %s memory hole at 0x%08x\n", op, addr); + assert(false); + } + } + + assert(!plat.avl_read || !plat.avl_write); + auto pos = addr >> 2; + + if(plat.avl_read) + { + plat.avl_waitrequest = !active->read(pos, plat.avl_readdata); + } else if(plat.avl_write) + { + plat.avl_waitrequest = !active->write(pos, plat.avl_writedata, plat.avl_byteenable); + } + + if(!plat.avl_waitrequest) + { + active = nullptr; + } + } +} + +#endif |
