Search code examples
simicsdml-lang

How do I properly model internal memory in my serial flash device?


I am writing a model for a serial flash device. I wonder how do I best model the internal memory? I would like the memory size to be configurable by the user since I intend to reuse this model for different serial flashes. It also needs to retain its content upon reset while the rest of the logic is reset.

I tried using a statically allocated character buffer but that is not configurable and seems very inappropriate for such large sizes as my flash model. My flash model is 512 MB.

saved char flash_image[512 * 1024 * 1024];


Solution

  • Assuming this will go into Simics, it is best modeled with two subobjects, both of which are available in Simics Base.

    The first is an image which stores the actual data, the second is a ram which is used to read/write into the image. Both the image and the ram are connects using the init_as_subobj template which makes Simics automatically create them as sub-objects of the device. They are placed in a group where we can add an init method, which sets default values for the required attributes of the subobjects; in this case the "size" of the image and the "image" of the ram.

    The ram object also uses the map_target template, which gives us useful methods for reading and writing into the ram.

    dml 1.4;
    
    device sample_dev;
    
    import "utility.dml";
    import "simics/simulator-api.dml";
    
    group flash is init {
        param size = 0x1000;
        method init() {
            SIM_set_attribute_default(
                ram.obj, "image", SIM_make_attr_object(image.obj));
            SIM_set_attribute_default(
                image.obj, "size", SIM_make_attr_uint64(size));
        }
    
        connect image is init_as_subobj {
            param classname = "image";
        }
    
        connect ram is (init_as_subobj, map_target) {
            param classname = "ram";
        }
    }
    
    
    method write_test() {
        try
            flash.ram.write(0, 1, 42);
        catch
            log error: "write failed, it shouldn't!";
    }
    
    

    The size of the image is given a default value by a parameter in this example, but it can also be set or overridden by the user when creating the object, by assigning to the attribute flash.image.size, e.g. like this:

    SIM_create_object("sample_dev", "dev", **{"flash.image.size": 0x2000})