The following is a naive implementation of the io_memory interface, designed to be used with the example device in Section 2.1 (note the references to $b in the code). To try it, simply remove the line "import "io-memory.dml";" from the original program, and instead add the below code (before or after the bank b {...} section).
implement io_memory { method map(addr_space_t mem, map_info_t info) -> (int status) { log "info": "Mapped function %d at %#x", info.function, info.base; status = 0; } method operation(generic_transaction_t *memop, map_info_t info) -> (exception_type_t ex) { if (info.function == $b.function) { local uint32 offset; offset = (memop->physical_address - info.base + info.start); log "info": "Accessing internal address %d", offset; call $b.access(memop, offset, memop->size); ex = Sim_PE_No_Exception; } else { ex = Sim_PE_IO_Not_Taken; } } }(The map method does not have to do anything, but should return zero. The operation method should return an "exception code" which is Sim_PE_No_Exception if all went well.)
The method declarations within an implement section are translated directly into C functions as expected by the Simics API; a pointer to the device object itself is automatically added as the first argument to each function. The methods can only have one or zero output parameters, which correspond directly to return values in C. In this example, the C function signatures for map and operation are:
int map(conf_object_t *obj, addr_space_t mem, map_info_t info); exception_type_t operation(conf_object_t *obj, generic_transaction_t *memop, map_info_t info)
Try recompiling and testing the device with this implementation of io_memory. For further details about the io_memory interface, and other Simics interfaces and datatypes, see the Simics Programming Guide and the Simics Reference Manual. (In general, the DML built-in constructs and standard libraries try to hide as much as possible about the details of the Simics API from the user.)