Jump to content
KEVIN CHACKO

How can I have a virtual interface in systemC analogous to systemverilog

Recommended Posts

SystemC has no special concept similar to SystemVerilog interfaces.  Instead you can use regular SystemC modules to work as SystemVerilog interfaces.

 

SystemC has it's own notion of interface that is similar to interface notion in object-oriented programming: interface is basically a set of pure virtual functions.

So for example you can define a simple memory interface as a set of mem_read and mem_write functions. SystemC requires that interfaces inherit virtually from sc_interface:

struct memory_if : virtual sc_interface {
    virtual uint32_t mem_read( uint32_t address) = 0; // reads data from memory at given address
    virtual void     mem_write( uint32_t address, uint32_t data) = 0; // writes data to memory at given address
};

Next you can define a module that implements and exports this interface.  For example:

struct memory_module : sc_module, memory_if {
    sc_export<memory_if>  mem_export{"mem_export"};

    SC_CTOR(memory_module) {
        mem_export.bind(*this);
    }

private:

    std::array<uint32_t , 1024> mem;

    uint32_t mem_read(uint32_t address) override {
        return mem.at(address >> 2);
    }

    void mem_write(uint32_t address, uint32_t data) override {
        mem.at(address >> 2) = data;
    }
};

You can have other modules implementing memory_if.  For example you can write a module that translates mem_read and mem_write function calls into a cycle-accurate signal-level memory protocol.  And this is what SystemVerilog interfaces often do.  

Now the closest analog to SystemVerilog virtual interface is SystemC sc_port. For example you can define a test_module that has a sc_port<memory_if> and sends memory reads and writes using this port:

struct test_module : sc_module {
  
    sc_port<memory_if> mem_port{"mem_port"};

    SC_CTOR(test_module) {
        SC_THREAD(test_thread);
    }
  
private:
    void test_thread() {
        cout << " test_thread \n";
        const int TEST_SIZE = 10;
        for (int i = 0; i < TEST_SIZE; ++i) {
            cout << hex << "Write mem[" << i * 4 << "] = " << i << "\n";
            mem_port->mem_write(i*4, i);
        }
        for (int i = 0; i < TEST_SIZE; ++i) {
            cout << hex << "Read mem[" << i * 4 << "] == " << mem_port->mem_read( i * 4 ) << "\n";
        }
    }
};

 

To create a simulation you instantiate both memory_module and test_module and bind port to export:

int sc_main (int argc, char **argv) {
    test_module tmod{"tmod"};
    memory_module mmod{"mmod"};
    tmod.mem_port.bind(mmod.mem_export);
    sc_start();
    return 0;
}

 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×