Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
sim:file [2024/02/26 18:56]
fabian
sim:file [2024/02/27 12:16] (current)
fabian
Line 1: Line 1:
 ====== File interaction ====== ====== File interaction ======
  
-This library exports functions for basic file interaction. Files in actsim can be accessed using the common simulator prefix and file IDs. The common prefix is set using an actsim configuration file. The following is a snippet from the default actsim configuration.+This library exports functions for basic file interaction. The exposed functions enable you to read integer data from a basic input file, and to dump integer values into an output file. While this is rather basic, the file API can be extended using a shared C++ library and an actsim configuration file. 
 + 
 +Files in actsim can be accessed using the common simulator prefix and file IDs. The common prefix is set using an actsim configuration file. The following is a snippet from the default actsim configuration.
  
 <code> <code>
Line 218: Line 220:
 } }
 </code> </code>
 +
 +===== Extending the File API =====
 +
 +File interactions can be extended using a shared C++ library, however the functions exposed to actsim must be made external C functions due to C++ name mangling. Include the ''simlib_file.h'' header to access the core file functions. With this, cou can use ''actsim_file_write_core'' to write your own custom output generator. Here is a brief example taken from the [[sim:loggers | logger]] output generation. For more information about the structure of an external C function callable from CHP, as well as how to make it accessible to actsim, see [[tools:actsim | the actsim page]] or read the default ''actsim.conf'' in the actsim source code in the ''simlib/'' directory.
 +
 +<code c>
 +extern "C" expr_res actsim_file_write_log(int argc, struct expr_res* args) {
 +    expr_res ret;
 +    ret.width = 1;
 +    ret.v = 1;  // on error we return 1
 +
 +    // make sure we have the appropriate amount of arguments
 +    if (argc != 5) {
 +        std::cerr
 +            << "actim_file_write_log: Must be invoked with 5 arguments only"
 +            << std::endl;
 +        return ret;
 +    }
 +
 +    uint32_t writer_id = args[0].v;
 +    uint8_t verbosity = args[1].v;
 +    uint32_t logger_id = args[2].v;
 +    uint32_t channel = args[3].v;
 +    uint64_t value = args[4].v;
 +
 +    // build the log line
 +    std::ostringstream builder;
 +
 +    switch (verbosity) {
 +        case 0:
 +            builder << channel << ":" << std::hex << value << std::endl;
 +            break;
 +
 +        case 1:
 +            builder << logger_id << " (" << channel << "): " << std::hex
 +                    << value << std::endl;
 +            break;
 +
 +        case 2:
 +            builder << "Logger " << logger_id << " (Channel " << channel
 +                    << "): Received value " << value << "%x (0x" << std::hex
 +                    << value << ")" << std::endl;
 +
 +        default:
 +            break;
 +    }
 +
 +    ret.v = actsim_file_write_core(writer_id, builder.str());
 +    return ret;
 +}
 +</code>
 +
 +When you have compiled your ''.so'', you need to make the library available to actsim via a configuration file:
 +
 +<code>
 +begin extern
 +
 +    string_tablex libs "mylib"
 +
 +    begin mylib
 +        string path "/some/path/to/my_external_lib.so"
 +
 +        # logger file output
 +        string my_namespace::write_log      "actsim_file_write_log"
 +    end
 +
 +end
 +</code>
 +
 +And finally, make the function available to CHP:
 +
 +<code act>
 +namespace my_namespace {
 +export function write_log (int<32> writer_id; int<8> verbosity; int<32> log_id, channel; int<64> val) : bool;
 +}
 +</code>
 +
 +Mind the name change set in the actsim configuration! Functions in CHP must always return a value. If you do not need a return value, either use a boolean in combination with an assert function for error checking, or just read into a dummy variable. Not reading into anything will currently cause your function to be removed by the optimization pass.