diff options
| author | Alejandro Soto <alejandro@34project.org> | 2022-09-18 00:39:21 -0600 |
|---|---|---|
| committer | Alejandro Soto <alejandro@34project.org> | 2022-09-18 00:39:21 -0600 |
| commit | d743c48b821bad11943b77bdc9a5d9d975fd8cb0 (patch) | |
| tree | 2097ce1618b876cc85172ea85c3165462e052c5e /tb/avalon.impl.hpp | |
| parent | b0cb20496d88cd017c4c51243d16ac3b060cc1d6 (diff) | |
Add Avalon-MM emulator
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 |
