Examples

The first example shows how to create and connect the AHB and APB bus controllers.

Connecting AHB and APB Controllers
import AhbCtrl
import ApbCtrl

# Create two bus objects
object-create class=AhbCtrl name=ahbctrl0
object-create class=ApbCtrl name=apbctrl0

# Map to the normal addresses
memory-map memspace=mem0 addr=0x800ff000 length=0x1000 object=apbctrl0
memory-map memspace=mem0 addr=0xfffff000 length=0x1000 object=ahbctrl0

# Connect various APB devices to the APB controller
connect a=apbctrl0.slaves b=ftmctrl0:ApbIface
connect a=apbctrl0.slaves b=apbuart0:ApbIface
connect a=apbctrl0.slaves b=irqMp0:ApbIface
connect a=apbctrl0.slaves b=gpTimer0:ApbIface
connect a=apbctrl0.slaves b=ahbstat0:ApbIface

# Connect various AHB devices to the AHB controller
connect a=ahbctrl0.masters b=cpu0:AhbIface
connect a=ahbctrl0.slaves b=ftmctrl0:AhbIface
connect a=ahbctrl0.slaves b=apbctrl0:AhbIface

The next example shows how to implement a simple APB device.

Simple Device with APB PNP Support
#include "temu-c/Bus/Amba.h"

// This is the model type, we need to add the Pnp info.
typedef struct MyDevice {
  temu_ApbPnpInfo Pnp;
  // ...
} MyDevice;


// Implement the APB PNP interface
temu_ApbPnpInfo*
getApbPnp(void *Obj)
{
   MyDevice *Dev = (MyDevice*)Obj;

   return &Dev->Pnp;
}

temu_ApbIface ApbIface = {
  .getApbPnp = getApbPnp
};


// Define functions to allocate and destroy the object
void*
create(int Argc, const temu_CreateArg *Argv)
{
  MyDevice *Dev = malloc(sizeof(MyDevice));
  memset(Dev, 0, sizeof(MyDevice));

  // PNP init
  temu_apbSetVendorId(&MyDevice->Pnp, 0x99);
  temu_apbSetDeviceId(&MyDevice->Pnp, 0x001);
  temu_apbSetVersion(&MyDevice->Pnp, 1);

  temu_apbSetAddr(&MyDevice->Pnp, 0);
  temu_apbSetCP(&MyDevice->Pnp, 0);
  temu_apbSetMask(&MyDevice->Pnp, 0xfff);
  temu_apbSetType(&MyDevice->Pnp, 1); // APB I/O space

  return MyDevice;
}

void
dispose(void *Obj)
{
  MyDevice *Dev = (MyDevice*)Obj;
  free(Irq);
}

// Define the device interface
void
reset(void *Obj, int ResetKind)
{
}

void
mapDevice(void *Obj, uint64_t Addr, uint64_t Len)
{
  MyDevice *Dev = (MyDevice*)Obj;
  temu_apbSetAddr(&Dev->Pnp, Addr);
}


temu_DeviceIface DeviceIface = {
  reset, // Called on resets
  mapDevice, // Called when a device is mapped to a memory location.
};



TEMU_PLUGIN_INIT
{
  temu_Class *cls = temu_registerClass("MyClass", create, dispose);

  temu_addInterface(cls, "ApbIface", "ApbIface", &ApbIface);
  temu_addInterface(cls, "DeviceIface", "DeviceIface", &DeviceIface);

}