summaryrefslogtreecommitdiff
path: root/tb/avalon.impl.hpp
diff options
context:
space:
mode:
authorAlejandro Soto <alejandro@34project.org>2022-09-18 00:39:21 -0600
committerAlejandro Soto <alejandro@34project.org>2022-09-18 00:39:21 -0600
commitd743c48b821bad11943b77bdc9a5d9d975fd8cb0 (patch)
tree2097ce1618b876cc85172ea85c3165462e052c5e /tb/avalon.impl.hpp
parentb0cb20496d88cd017c4c51243d16ac3b060cc1d6 (diff)
Add Avalon-MM emulator
Diffstat (limited to '')
-rw-r--r--tb/avalon.impl.hpp62
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