void createPlatformArm(char *kernelFile, char *ramDisk, Uns32 icmAttrs) {

    icmPrintf("createPlatform ARM icmAttrs 0x%x\n"
              "  Files: kernelFile %s\n"
              "         ramDisk %s\n"
              "  Variant ARM %s \n", icmAttrs, kernelFile, ramDisk, variantArm);

////////////////////////////////////////////////////////////////////////////////
//                                 Bus bus1_b
////////////////////////////////////////////////////////////////////////////////

    icmBusP bus1_b = icmNewBus( "bus1_b", 32);


////////////////////////////////////////////////////////////////////////////////
//                                Bus membus_b
////////////////////////////////////////////////////////////////////////////////

    icmBusP membus_b = icmNewBus( "membus_b", 32);


////////////////////////////////////////////////////////////////////////////////
//                               Processor arm1
////////////////////////////////////////////////////////////////////////////////

    const char *arm1_path = icmGetVlnvString(
        0,    // path (0 if from the product directory)
        "arm.ovpworld.org",    // vendor
        0,    // library
        "arm",    // name
        0,    // version
        "model"     // model
    );

    icmAttrListP arm1_attr = icmNewAttrList();

    icmAddStringAttr(arm1_attr, "variant", variantArm);
    icmAddStringAttr(arm1_attr, "compatibility", "ISA");
    icmAddStringAttr(arm1_attr, "showHiddenRegs", "0");
    icmAddDoubleAttr(arm1_attr, "mips", 200.000000);
    icmAddStringAttr(arm1_attr, "endian", "little");

    icmProcessorP arm1_c = icmNewProcessor(
        "arm1",   // name
        "arm",   // type
        0,   // cpuId
        0x0, // flags
         32,   // address bits
        arm1_path,   // model
        "modelAttrs",   // symbol
        0x20,   // procAttrs
        arm1_attr,   // attrlist
        0,   // semihost file
        0    // semihost symbol
    );

    icmConnectProcessorBusses( arm1_c, bus1_b, bus1_b );

////////////////////////////////////////////////////////////////////////////////
//                                   PSE cm
////////////////////////////////////////////////////////////////////////////////

    const char *cm_path = icmGetVlnvString(
        0,    // path (0 if from the product directory)
        0,    // vendor
        0,    // library
        "CoreModule9x6",    // name
        0,    // version
        "pse"     // model
    );

    icmAttrListP cm_attr = icmNewAttrList();


    icmPseP cm_p = icmNewPSE(
        "cm",   // name
        cm_path,   // model
        cm_attr,   // attrlist
        0,   // semihost file
        0    // semihost symbol
    );

    icmConnectPSEBus( cm_p, bus1_b, "bport1", 0, 0x10000000, 0x10000fff);


////////////////////////////////////////////////////////////////////////////////
//                                  PSE pic1
////////////////////////////////////////////////////////////////////////////////

    const char *pic1_path = icmGetVlnvString(
        0,    // path (0 if from the product directory)
        0,    // vendor
        0,    // library
        "IntICP",    // name
        0,    // version
        "pse"     // model
    );

    icmAttrListP pic1_attr = icmNewAttrList();


    icmPseP pic1_p = icmNewPSE(
        "pic1",   // name
        pic1_path,   // model
        pic1_attr,   // attrlist
        0,   // semihost file
        0    // semihost symbol
    );

    icmConnectPSEBus( pic1_p, bus1_b, "bport1", 0, 0x14000000, 0x14000fff);


////////////////////////////////////////////////////////////////////////////////
//                                  PSE pic2
////////////////////////////////////////////////////////////////////////////////

    const char *pic2_path = icmGetVlnvString(
        0,    // path (0 if from the product directory)
        0,    // vendor
        0,    // library
        "IntICP",    // name
        0,    // version
        "pse"     // model
    );

    icmAttrListP pic2_attr = icmNewAttrList();


    icmPseP pic2_p = icmNewPSE(
        "pic2",   // name
        pic2_path,   // model
        pic2_attr,   // attrlist
        0,   // semihost file
        0    // semihost symbol
    );

    icmConnectPSEBus( pic2_p, bus1_b, "bport1", 0, 0xca000000, 0xca000fff);


////////////////////////////////////////////////////////////////////////////////
//                                   PSE pit
////////////////////////////////////////////////////////////////////////////////

    const char *pit_path = icmGetVlnvString(
        0,    // path (0 if from the product directory)
        0,    // vendor
        0,    // library
        "IcpCounterTimer",    // name
        0,    // version
        "pse"     // model
    );

    icmAttrListP pit_attr = icmNewAttrList();


    icmPseP pit_p = icmNewPSE(
        "pit",   // name
        pit_path,   // model
        pit_attr,   // attrlist
        0,   // semihost file
        0    // semihost symbol
    );

    icmConnectPSEBus( pit_p, bus1_b, "bport1", 0, 0x13000000, 0x13000fff);


////////////////////////////////////////////////////////////////////////////////
//                                   PSE icp
////////////////////////////////////////////////////////////////////////////////

    const char *icp_path = icmGetVlnvString(
        0,    // path (0 if from the product directory)
        0,    // vendor
        0,    // library
        "IcpControl",    // name
        0,    // version
        "pse"     // model
    );

    icmAttrListP icp_attr = icmNewAttrList();


    icmPseP icp_p = icmNewPSE(
        "icp",   // name
        icp_path,   // model
        icp_attr,   // attrlist
        0,   // semihost file
        0    // semihost symbol
    );

    icmConnectPSEBus( icp_p, bus1_b, "bport1", 0, 0xcb000000, 0xcb00000f);


////////////////////////////////////////////////////////////////////////////////
//                                   PSE ld1
////////////////////////////////////////////////////////////////////////////////

    const char *ld1_path = icmGetVlnvString(
        0,    // path (0 if from the product directory)
        0,    // vendor
        0,    // library
        "DebugLedAndDipSwitch",    // name
        0,    // version
        "pse"     // model
    );

    icmAttrListP ld1_attr = icmNewAttrList();


    icmPseP ld1_p = icmNewPSE(
        "ld1",   // name
        ld1_path,   // model
        ld1_attr,   // attrlist
        0,   // semihost file
        0    // semihost symbol
    );

    icmConnectPSEBus( ld1_p, bus1_b, "bport1", 0, 0x1a000000, 0x1a000fff);


////////////////////////////////////////////////////////////////////////////////
//                                   PSE kb1
////////////////////////////////////////////////////////////////////////////////

    const char *kb1_path = icmGetVlnvString(
        0,    // path (0 if from the product directory)
        0,    // vendor
        0,    // library
        "KbPL050",    // name
        0,    // version
        "pse"     // model
    );

    icmAttrListP kb1_attr = icmNewAttrList();

    icmAddUns64Attr(kb1_attr, "isMouse", 0);
    icmAddUns64Attr(kb1_attr, "grabDisable", 0);

    icmPseP kb1_p = icmNewPSE(
        "kb1",   // name
        kb1_path,   // model
        kb1_attr,   // attrlist
        0,   // semihost file
        "modelAttrs"    // semihost symbol
    );

    icmConnectPSEBus( kb1_p, bus1_b, "bport1", 0, 0x18000000, 0x18000fff);


////////////////////////////////////////////////////////////////////////////////
//                                   PSE ms1
////////////////////////////////////////////////////////////////////////////////

    const char *ms1_path = icmGetVlnvString(
        0,    // path (0 if from the product directory)
        0,    // vendor
        0,    // library
        "KbPL050",    // name
        0,    // version
        "pse"     // model
    );

    icmAttrListP ms1_attr = icmNewAttrList();

    icmAddUns64Attr(ms1_attr, "isMouse", 1);
    icmAddUns64Attr(ms1_attr, "grabDisable", 1);

    icmPseP ms1_p = icmNewPSE(
        "ms1",   // name
        ms1_path,   // model
        ms1_attr,   // attrlist
        0,   // semihost file
        "modelAttrs"    // semihost symbol
    );

    icmConnectPSEBus( ms1_p, bus1_b, "bport1", 0, 0x19000000, 0x19000fff);


////////////////////////////////////////////////////////////////////////////////
//                                   PSE rtc
////////////////////////////////////////////////////////////////////////////////

    const char *rtc_path = icmGetVlnvString(
        0,    // path (0 if from the product directory)
        0,    // vendor
        0,    // library
        "RtcPL031",    // name
        0,    // version
        "pse"     // model
    );

    icmAttrListP rtc_attr = icmNewAttrList();


    icmPseP rtc_p = icmNewPSE(
        "rtc",   // name
        rtc_path,   // model
        rtc_attr,   // attrlist
        0,   // semihost file
        0    // semihost symbol
    );

    icmConnectPSEBus( rtc_p, bus1_b, "bport1", 0, 0x15000000, 0x15000fff);


////////////////////////////////////////////////////////////////////////////////
//                                  PSE uart1
////////////////////////////////////////////////////////////////////////////////

    const char *uart1_path = icmGetVlnvString(
        0,    // path (0 if from the product directory)
        0,    // vendor
        0,    // library
        "UartPL011",    // name
        0,    // version
        "pse"     // model
    );


    icmAttrListP uart1_attr = icmNewAttrList();
    icmAddStringAttr(uart1_attr, "variant", "ARM");
    icmAddStringAttr(uart1_attr, "outfile", "arm-uart1.log");
    if(connectARMUartPort) {
        if(!uartPort) {
            icmAddUns64Attr(uart1_attr, "console", 1);
        } else {
            icmAddUns64Attr(uart1_attr, "portnum", uartPort);
        }
        icmAddUns64Attr(uart1_attr, "finishOnDisconnect", 1);
    }

    icmPseP uart1_p = icmNewPSE(
        "uart1",       // name
        uart1_path,   // model
        uart1_attr,   // attrlist
        NULL,         // semihost file
        NULL          // semihost symbol
    );

    icmConnectPSEBus( uart1_p, bus1_b, "bport1", 0, 0x16000000, 0x16000fff);
    if(connectARMUartPort) {
        icmSetPSEdiagnosticLevel(uart1_p, 1);
    }

////////////////////////////////////////////////////////////////////////////////
//                                  PSE uart2
////////////////////////////////////////////////////////////////////////////////

    const char *uart2_path = icmGetVlnvString(
        0,    // path (0 if from the product directory)
        0,    // vendor
        0,    // library
        "UartPL011",    // name
        0,    // version
        "pse"     // model
    );

    icmAttrListP uart2_attr = icmNewAttrList();
    icmAddStringAttr(uart2_attr, "variant", "ARM");
    icmAddStringAttr(uart2_attr, "outfile", "arm-uart2.log");

    icmPseP uart2_p = icmNewPSE(
        "uart2",   // name
        uart2_path,   // model
        uart2_attr,   // attrlist
        NULL,   // semihost file
        NULL    // semihost symbol
    );

    icmConnectPSEBus( uart2_p, bus1_b, "bport1", 0, 0x17000000, 0x17000fff);


////////////////////////////////////////////////////////////////////////////////
//                                  PSE mmci
////////////////////////////////////////////////////////////////////////////////

    const char *mmci_path = icmGetVlnvString(
        0,    // path (0 if from the product directory)
        0,    // vendor
        0,    // library
        "MmciPL181",    // name
        0,    // version
        "pse"     // model
    );

    icmAttrListP mmci_attr = icmNewAttrList();


    icmPseP mmci_p = icmNewPSE(
        "mmci",   // name
        mmci_path,   // model
        mmci_attr,   // attrlist
        0,   // semihost file
        "modelAttrs"    // semihost symbol
    );

    icmConnectPSEBus( mmci_p, bus1_b, "bport1", 0, 0x1c000000, 0x1c000fff);


////////////////////////////////////////////////////////////////////////////////
//                                   PSE lcd
////////////////////////////////////////////////////////////////////////////////

    const char *lcd_path = icmGetVlnvString(
        0,    // path (0 if from the product directory)
        0,    // vendor
        0,    // library
        "LcdPL110",    // name
        0,    // version
        "pse"     // model
    );

    icmAttrListP lcd_attr = icmNewAttrList();

    icmAddUns64Attr(lcd_attr, "scanDelay", 50000);
	icmAddDoubleAttr(lcd_attr, "noGraphics", noGraphics);
	icmAddDoubleAttr(lcd_attr, "busOffset",  0x80000000);

    icmPseP lcd_p = icmNewPSE(
        "lcd",   // name
        lcd_path,   // model
        lcd_attr,   // attrlist
        0,   // semihost file
        "modelAttrs"    // semihost symbol
    );

    icmConnectPSEBus( lcd_p, bus1_b, "bport1", 0, 0xc0000000, 0xc0000fff);

    icmConnectPSEBusDynamic( lcd_p, membus_b, "memory", 0);


////////////////////////////////////////////////////////////////////////////////
//                               PSE smartLoader
////////////////////////////////////////////////////////////////////////////////

    const char *smartLoader_path = icmGetVlnvString(
        0,    // path (0 if from the product directory)
        "arm.ovpworld.org",    // vendor
        0,    // library
        "SmartLoaderArmLinux",    // name
        0,    // version
        "pse"     // model
    );

    icmAttrListP smartLoader_attr = icmNewAttrList();
    if(programLoad) {
        icmAddStringAttr(smartLoader_attr, "disable", "1");
    } else {
        icmAddStringAttr(smartLoader_attr, "initrd", ramDisk);
        icmAddStringAttr(smartLoader_attr, "kernel", kernelFile);
    }


    icmPseP smartLoader_p = icmNewPSE(
        "smartLoader",   // name
        smartLoader_path,   // model
        smartLoader_attr,   // attrlist
        0,   // semihost file
        0    // semihost symbol
    );

    icmConnectPSEBus( smartLoader_p, bus1_b, "mport", 1, 0x0, 0xffffffff);


////////////////////////////////////////////////////////////////////////////////
//                                 Memory ram1
////////////////////////////////////////////////////////////////////////////////

    icmMemoryP ram1_m = icmNewMemory("ram1_m", 0x7, 0x7ffffff);

    icmConnectMemoryToBus( membus_b, "sp1", ram1_m, 0x0);


////////////////////////////////////////////////////////////////////////////////
//                              Memory ambaDummy
////////////////////////////////////////////////////////////////////////////////

    icmMemoryP ambaDummy_m = icmNewMemory("ambaDummy_m", 0x7, 0xfff);

    icmConnectMemoryToBus( bus1_b, "sp1", ambaDummy_m, 0x1d000000);


////////////////////////////////////////////////////////////////////////////////
//                              Bridge ram1Bridge
////////////////////////////////////////////////////////////////////////////////

    icmNewBusBridge(bus1_b, membus_b, "ram1Bridge", "sp", "mp", 0x0, 0x7ffffff, 0x0);


////////////////////////////////////////////////////////////////////////////////
//                              Bridge ram2Bridge
////////////////////////////////////////////////////////////////////////////////

    icmNewBusBridge(bus1_b, membus_b, "ram2Bridge", "sp1", "mp", 0x0, 0x7ffffff, 0x80000000);


////////////////////////////////////////////////////////////////////////////////
//                                 CONNECTIONS
////////////////////////////////////////////////////////////////////////////////

    icmNetP irq_n = icmNewNet("irq_n" );

    icmConnectProcessorNet( arm1_c, irq_n, "irq", ICM_INPUT);

    icmConnectPSENet( pic1_p, irq_n, "irq", ICM_OUTPUT);

////////////////////////////////////////////////////////////////////////////////
    icmNetP fiq_n = icmNewNet("fiq_n" );

    icmConnectProcessorNet( arm1_c, fiq_n, "fiq", ICM_INPUT);

    icmConnectPSENet( pic1_p, fiq_n, "fiq", ICM_OUTPUT);

////////////////////////////////////////////////////////////////////////////////
    icmNetP ir1_n = icmNewNet("ir1_n" );

    icmConnectPSENet( pic1_p, ir1_n, "ir1", ICM_INPUT);

    icmConnectPSENet( uart1_p, ir1_n, "irq", ICM_OUTPUT);

////////////////////////////////////////////////////////////////////////////////
    icmNetP ir2_n = icmNewNet("ir2_n" );

    icmConnectPSENet( pic1_p, ir2_n, "ir2", ICM_INPUT);

    icmConnectPSENet( uart2_p, ir2_n, "irq", ICM_OUTPUT);

////////////////////////////////////////////////////////////////////////////////
    icmNetP ir3_n = icmNewNet("ir3_n" );

    icmConnectPSENet( pic1_p, ir3_n, "ir3", ICM_INPUT);

    icmConnectPSENet( kb1_p, ir3_n, "irq", ICM_OUTPUT);

////////////////////////////////////////////////////////////////////////////////
    icmNetP ir4_n = icmNewNet("ir4_n" );

    icmConnectPSENet( pic1_p, ir4_n, "ir4", ICM_INPUT);

    icmConnectPSENet( ms1_p, ir4_n, "irq", ICM_OUTPUT);

////////////////////////////////////////////////////////////////////////////////
    icmNetP ir5_n = icmNewNet("ir5_n" );

    icmConnectPSENet( pic1_p, ir5_n, "ir5", ICM_INPUT);

    icmConnectPSENet( pit_p, ir5_n, "irq0", ICM_OUTPUT);

////////////////////////////////////////////////////////////////////////////////
    icmNetP ir6_n = icmNewNet("ir6_n" );

    icmConnectPSENet( pic1_p, ir6_n, "ir6", ICM_INPUT);

    icmConnectPSENet( pit_p, ir6_n, "irq1", ICM_OUTPUT);

////////////////////////////////////////////////////////////////////////////////
    icmNetP ir7_n = icmNewNet("ir7_n" );

    icmConnectPSENet( pic1_p, ir7_n, "ir7", ICM_INPUT);

    icmConnectPSENet( pit_p, ir7_n, "irq2", ICM_OUTPUT);

////////////////////////////////////////////////////////////////////////////////
    icmNetP ir8_n = icmNewNet("ir8_n" );

    icmConnectPSENet( pic1_p, ir8_n, "ir8", ICM_INPUT);

    icmConnectPSENet( rtc_p, ir8_n, "irq", ICM_OUTPUT);

////////////////////////////////////////////////////////////////////////////////
    icmNetP ir23_n = icmNewNet("ir23_n" );

    icmConnectPSENet( pic1_p, ir23_n, "ir23", ICM_INPUT);

    icmConnectPSENet( mmci_p, ir23_n, "irq0", ICM_OUTPUT);

////////////////////////////////////////////////////////////////////////////////
    icmNetP ir24_n = icmNewNet("ir24_n" );

    icmConnectPSENet( pic1_p, ir24_n, "ir24", ICM_INPUT);

    icmConnectPSENet( mmci_p, ir24_n, "irq1", ICM_OUTPUT);

////////////////////////////////////////////////////////////////////////////////

    if(programLoad) {
        if(icmLoadProcessorMemory(arm1_c, kernelFile, ICM_LOAD_DEFAULT, True, True)) {
            // All files loaded correctly
        } else {
            icmPrintf("Failed to load %s\n", kernelFile);
            exit(1);
        }
    }

}
//
// Virtual platform construction and simulation
//
int main(int argc, const char **argv) {

    // Check arguments
    if(!cmdParser(argc, argv)) {
    	icmMessage("E", PLATFORM, "Command Line parser error");
    	return 1;
    }

    // initialize OVPsim
    unsigned int icmAttrs = ICM_STOP_ON_CTRLC;

    icmInitPlatform(ICM_VERSION, icmAttrs, 0, 0, PLATFORM);

    const char *modelFile    = "model." IMPERAS_SHRSUF;
    const char *semihostFile = icmGetVlnvString(NULL, "ovpworld.org", "modelSupport", "imperasExit", "1.0", "model");

    // create a processor instance
    icmProcessorP procA = icmNewProcessor(
        "procA",            // CPU name
        "or1k",             // CPU type
        0,                  // CPU cpuId
        0,                  // CPU model flags
        32,                 // address bits
        modelFile,          // model file
        "modelAttrs",       // morpher attributes
		MODEL_FLAGS,        // attributes
        0,                  // user-defined attributes
        semihostFile,       // semi-hosting file
        "modelAttrs"        // semi-hosting attributes
    );

    // create the processor bus
    icmBusP busA = icmNewBus("busA", 32);

    // connect the processors onto the busses
    icmConnectProcessorBusses(procA, busA, busA);

    // create memory
    icmMemoryP localA = icmNewMemory("localA", ICM_PRIV_RWX, 0xffffffff);

    // connect the memory onto the busses
    icmConnectMemoryToBus(busA, "mp1", localA, 0x00000000);


    // create a processor instance
    icmProcessorP procB = icmNewProcessor(
        "procB",             // CPU name
        "or1k",             // CPU type
        0,                  // CPU cpuId
        0,                  // CPU model flags
        32,                 // address bits
        modelFile,          // model file
        "modelAttrs",       // morpher attributes
		MODEL_FLAGS,        // attributes
        attrsForB(),        // user-defined attributes
        semihostFile,       // semi-hosting file
        "modelAttrs"        // semi-hosting attributes
    );

    // create the processor bus
    icmBusP busB = icmNewBus("busB", 32);

    // connect the processors onto the busses
    icmConnectProcessorBusses(procB, busB, busB);

    // create memory
    icmMemoryP localB = icmNewMemory("localB", ICM_PRIV_RWX, 0xffffffff);

    // connect the memory onto the busses
    icmConnectMemoryToBus(busB, "mp1", localB, 0x00000000);

    icmNetP n1 = icmNewNet("n1");
    icmNetP n2 = icmNewNet("n2");
    icmNetP n3 = icmNewNet("n3");

    icmConnectProcessorNet(procA, n1, "intr0", ICM_INPUT);
    icmConnectProcessorNet(procB, n2, "intr0", ICM_INPUT);
    icmConnectProcessorNet(procB, n3, "intr1", ICM_INPUT);

    // advance the processors, then interrupt
    icmSimulate(procA, 9);
    icmSimulate(procB, 9);
    icmPrintf("Interrupting A & B\n");
    icmWriteNet(n1, 1);
    icmWriteNet(n3, 1);
    icmSimulate(procA, 1);
    icmSimulate(procB, 1);
    icmWriteNet(n1, 0);
    icmWriteNet(n3, 0);
    icmSimulate(procA, 9);
    icmSimulate(procB, 9);

    icmPrintf("Interrupting B\n");
    icmWriteNet(n2, 1);
    icmSimulate(procA, 1);
    icmSimulate(procB, 1);
    icmWriteNet(n2, 0);
    icmSimulate(procA, 10);
    icmSimulate(procB, 10);

    // report the total number of instructions executed
    icmPrintf(
        "processor A has executed " FMT_64u " instructions\n",
        icmGetProcessorICount(procA)
    );
    icmPrintf(
        "processor B has executed " FMT_64u " instructions\n",
        icmGetProcessorICount(procB)
    );

    icmTerminate();

    return 0;
}
// Platform entry point
int main(int argc, char **argv) {

    // Get the name of the application to run from the command line
    if (argc != 2) {
        icmPrintf("usage: %s <pa application>\n", argv[0]);
        return -1;
    }

    // Initialize OVPsim, enabling verbose mode to get statistics at end of execution
    icmInit(ICM_VERBOSE | ICM_STOP_ON_CTRLC | ICM_ENABLE_IMPERAS_INTERCEPTS, NULL, 0);

    /***************************************************************************************************
       MURAC Primary Architecture
         - ARM processor
     ***************************************************************************************************/
#ifdef INTECEPT_OBJECT_SUPPORTED
    const char *armModel    = icmGetVlnvString(NULL, "arm.ovpworld.org", "processor", "arm", "1.0", "model");
#endif
    const char *armSemihost = icmGetVlnvString(NULL, "arm.ovpworld.org", "semihosting", "armNewlib", "1.0", "model");

    icmAttrListP armUserAttr = icmNewAttrList();
    icmAddStringAttr(armUserAttr, "compatibility", "gdb");
    icmAddStringAttr(armUserAttr, "variant", "Cortex-A8");
    icmAddStringAttr(armUserAttr, "UAL", "1");

    // Create the Primary Architecture (PA) processor
    icmProcessorP pa = icmNewProcessor(
        "pa",                // CPU name
        "arm",               // CPU type
        0,                   // CPU cpuId
        0,                   // CPU model flags
        32,                  // address bits
#ifdef INTECEPT_OBJECT_SUPPORTED
        armModel,            // model file
#else

        MURAC_PA_MODEL_FILE, // model file
#endif
        "modelAttrs",        // model attributes
        SIMULATION_FLAGS,    // simulation flags
        armUserAttr,         // user-defined attributes
        armSemihost,         // semi-hosting file
        "modelAttrs"         // semi-hosting attributes
    );

#ifdef INTECEPT_OBJECT_SUPPORTED
    // Add intercept libarary for MURAC Primary Architecture instructions
    icmAddInterceptObject(pa, "murac_pa", MURAC_PA_INSTRUCTIONS_FILE, "modelAttrs", 0);
#endif

    /***************************************************************************************************
       System Memory
     ***************************************************************************************************/
    // Local memory for the PA
    // the ARM processor toolchain sites code in lower memory and stack in higher memory
    // so we will use two memories
    // NOTE: this is just a consequence of the default linker script used
    icmMemoryP codeMemory = icmNewMemory("code_memory", ICM_PRIV_RWX, 0x9fffffff);
    icmMemoryP localPA    = icmNewMemory("local_pa_memory", ICM_PRIV_RWX, 0x0fffffff);

    // Local memory for the AA
    icmMemoryP localAA    = icmNewMemory("local_aa_memory", ICM_PRIV_RWX, 0x0fffffff);

    // Processor state memory (shared)
    icmMemoryP prStateMemory = icmNewMemory("pr_state_memory", ICM_PRIV_RWX, 0x100);

    /***************************************************************************************************
       System Bus connections
     ***************************************************************************************************/
    icmBusP busPA = icmNewBus("pa_bus", 32);
    icmBusP busAA = icmNewBus("aa_bus", 32);

    // Connect Primary Architecture to the pa bus
    icmConnectProcessorBusses(pa, busPA, busPA);

    // Connect memories to the busses
    icmConnectMemoryToBus(busPA, "pa_code_memory_port", codeMemory, 0x00000000);
    icmConnectMemoryToBus(busPA, "pa_local_memory_port", localPA, 0xf0000000);
    icmConnectMemoryToBus(busPA, "pa_pr_state_memory_port", prStateMemory, 0xcf000000);

    icmConnectMemoryToBus(busAA, "aa_code_memory_port", codeMemory, 0x00000000);
    icmConnectMemoryToBus(busAA, "aa_local_memory_port", localAA, 0xf0000000);
    icmConnectMemoryToBus(busAA, "aa_pr_state_memory_port", prStateMemory, 0xcf000000);

    /***************************************************************************************************
       MURAC Peripherals (Auxiliary Architecture)
     ***************************************************************************************************/
    icmAttrListP fpgaAttrs = icmNewAttrList();
    if(finishOnSoftReset) {
        icmAddUns64Attr(fpgaAttrs, "stoponsoftreset",  1);
    }
    icmPseP muracFpga = icmNewPSE("muracFpga", MURAC_AA_FPGA_PSE_FILE, fpgaAttrs, 0, 0);

    // Connect memory access ports to the bus
    icmConnectPSEBus(muracFpga, busAA, "fpga_memread", True, 0x00000000, 0xffffffff);
    icmConnectPSEBus(muracFpga, busAA, "fpga_memwrite", True, 0x00000000, 0xffffffff);
    
    /***************************************************************************************************
       System Interrupt connections
     ***************************************************************************************************/
    icmNetP intBrArch = icmNewNet("brArch");
    icmNetP intRetArch = icmNewNet("retArch");

    // connect the processor interrupt port to the net
    icmConnectProcessorNet(pa, intBrArch, "brarch", ICM_OUTPUT);
    // connect the FPGA interrupt port to the net
    icmConnectPSENet(muracFpga, intBrArch, "fpga_brarch", ICM_INPUT);

    // connect the processor interrupt port to the net
    icmConnectProcessorNet(pa, intRetArch, "fiq", ICM_INPUT);
    // connect the FPGA interrupt port to the net
    icmConnectPSENet(muracFpga, intRetArch, "fpga_retarch", ICM_OUTPUT);

    /***************************************************************************************************
       Information
     ***************************************************************************************************/

    // Show the bus connections
    icmPrintf("\nPrimary Architecture Bus Connections\n");
    icmPrintBusConnections(busPA);
    icmPrintf("\nAuxiliary Architecture Bus Connections\n");
    icmPrintBusConnections(busAA);
    icmPrintf("\nNet Connections\n");
    icmPrintNetConnections();
    icmPrintf("\n");

    /***************************************************************************************************
       MURAC Simulation
     ***************************************************************************************************/

    // Load the application code into the primary architecture memory
    icmLoadProcessorMemory(pa, argv[1], False, False, True);

    // Run the simulation until done (no instruction limit)
    icmProcessorP final = icmSimulatePlatform();
    if ( final && (icmGetStopReason(final) == ICM_SR_INTERRUPT ) ) {
        icmPrintf("*** MURAC simulation interrupted\n");
    }

    // report the total number of instructions executed
    icmPrintf("MURAC Primary Architecture has executed " FMT_64u " instructions\n", icmGetProcessorICount(pa));

    icmTerminate();
    
    return 0;

}
void createPlatformArm(Uns32 icmAttrs) {


////////////////////////////////////////////////////////////////////////////////
//                                 Bus smbus_b
////////////////////////////////////////////////////////////////////////////////

    icmBusP smbus_b = icmNewBus( "smbus_b", 32);


////////////////////////////////////////////////////////////////////////////////
//                                Bus ddr2bus_b
////////////////////////////////////////////////////////////////////////////////

    icmBusP ddr2bus_b = icmNewBus( "ddr2bus_b", 32);


////////////////////////////////////////////////////////////////////////////////
//                               Processor cpu0
////////////////////////////////////////////////////////////////////////////////

    const char *cpu_path = icmGetVlnvString(
        0,    // path (0 if from the product directory)
        modelVendor,    // vendor
        0,    // library
        "arm",    // name
        modelVersion,    // version
        "model"     // model
    );

    icmAttrListP cpu_attr = icmNewAttrList();

    icmAddStringAttr(cpu_attr, "variant", variantArm);
    icmAddStringAttr(cpu_attr, "compatibility", "ISA");
    icmAddStringAttr(cpu_attr, "showHiddenRegs", "0");
    icmAddStringAttr(cpu_attr, "UAL", "1");
    icmAddUns64Attr(cpu_attr, "override_CBAR", 503316480);
    icmAddDoubleAttr(cpu_attr, "mips", 448.000000);
    icmAddStringAttr(cpu_attr, "endian", "little");

    icmProcessorP cpu_c = icmNewProcessor(
        "cpu",   // name
        "arm",   // type
        0,   // cpuId
        0x0, // flags
         32,   // address bits
        cpu_path,   // model
        "modelAttrs",   // symbol
        0x20,   // procAttrs
        cpu_attr,   // attrlist
        0,   // semihost file
        0    // semihost symbol
    );

    icmConnectProcessorBusses( cpu_c, smbus_b, smbus_b );


////////////////////////////////////////////////////////////////////////////////
//                                 PSE sysRegs
////////////////////////////////////////////////////////////////////////////////

    const char *sysRegs_path = icmGetVlnvString(
        0,    // path (0 if from the product directory)
        0,    // vendor
        0,    // library
        "VexpressSysRegs",    // name
        0,    // version
        "pse"     // model
    );

    icmAttrListP sysRegs_attr = icmNewAttrList();


    icmPseP sysRegs_p = icmNewPSE(
        "sysRegs",   // name
        sysRegs_path,   // model
        sysRegs_attr,   // attrlist
        0,   // semihost file
        0    // semihost symbol
    );

    icmConnectPSEBus( sysRegs_p, smbus_b, "bport1", 0, 0x10000000, 0x10000fff);


////////////////////////////////////////////////////////////////////////////////
//                                 PSE sysCtrl
////////////////////////////////////////////////////////////////////////////////

    const char *sysCtrl_path = icmGetVlnvString(
        0,    // path (0 if from the product directory)
        0,    // vendor
        0,    // library
        "SysCtrlSP810",    // name
        0,    // version
        "pse"     // model
    );

    icmAttrListP sysCtrl_attr = icmNewAttrList();


    icmPseP sysCtrl_p = icmNewPSE(
        "sysCtrl",   // name
        sysCtrl_path,   // model
        sysCtrl_attr,   // attrlist
        0,   // semihost file
        0    // semihost symbol
    );

    icmConnectPSEBus( sysCtrl_p, smbus_b, "bport1", 0, 0x10001000, 0x10001fff);


////////////////////////////////////////////////////////////////////////////////
//                                  PSE aac1
////////////////////////////////////////////////////////////////////////////////

    const char *aac1_path = icmGetVlnvString(
        0,    // path (0 if from the product directory)
        0,    // vendor
        0,    // library
        "AaciPL041",    // name
        0,    // version
        "pse"     // model
    );

    icmAttrListP aac1_attr = icmNewAttrList();


    icmPseP aac1_p = icmNewPSE(
        "aac1",   // name
        aac1_path,   // model
        aac1_attr,   // attrlist
        0,   // semihost file
        0    // semihost symbol
    );

    icmConnectPSEBus( aac1_p, smbus_b, "bport1", 0, 0x10004000, 0x10004fff);


////////////////////////////////////////////////////////////////////////////////
//                                  PSE mmc1
////////////////////////////////////////////////////////////////////////////////

    const char *mmc1_path = icmGetVlnvString(
        0,    // path (0 if from the product directory)
        0,    // vendor
        0,    // library
        "MmciPL181",    // name
        0,    // version
        "pse"     // model
    );

    icmAttrListP mmc1_attr = icmNewAttrList();

    if (loadSDCard) {
        icmAddStringAttr(mmc1_attr, "SD_DRIVE", sdCardImage);
    }


    icmPseP mmc1_p = icmNewPSE(
        "mmc1",   // name
        mmc1_path,   // model
        mmc1_attr,   // attrlist
        0,   // semihost file
        "modelAttrs"    // semihost symbol
    );


    icmConnectPSEBus( mmc1_p, smbus_b, "bport1", 0, 0x10005000, 0x10005fff);


////////////////////////////////////////////////////////////////////////////////
//                                   PSE kb1
////////////////////////////////////////////////////////////////////////////////

    const char *kb1_path = icmGetVlnvString(
        0,    // path (0 if from the product directory)
        0,    // vendor
        0,    // library
        "KbPL050",    // name
        0,    // version
        "pse"     // model
    );

    icmAttrListP kb1_attr = icmNewAttrList();

    icmAddUns64Attr(kb1_attr, "isKeyboard", 1);
    icmAddUns64Attr(kb1_attr, "grabDisable", 1);

    icmPseP kb1_p = icmNewPSE(
        "kb1",   // name
        kb1_path,   // model
        kb1_attr,   // attrlist
        0,   // semihost file
        "modelAttrs"    // semihost symbol
    );

    icmConnectPSEBus( kb1_p, smbus_b, "bport1", 0, 0x10006000, 0x10006fff);


////////////////////////////////////////////////////////////////////////////////
//                                   PSE ms1
////////////////////////////////////////////////////////////////////////////////

    const char *ms1_path = icmGetVlnvString(
        0,    // path (0 if from the product directory)
        0,    // vendor
        0,    // library
        "KbPL050",    // name
        0,    // version
        "pse"     // model
    );

    icmAttrListP ms1_attr = icmNewAttrList();

    icmAddUns64Attr(ms1_attr, "isMouse", 1);
    icmAddUns64Attr(ms1_attr, "grabDisable", 1);

    icmPseP ms1_p = icmNewPSE(
        "ms1",   // name
        ms1_path,   // model
        ms1_attr,   // attrlist
        0,   // semihost file
        "modelAttrs"    // semihost symbol
    );

    icmConnectPSEBus( ms1_p, smbus_b, "bport1", 0, 0x10007000, 0x10007fff);


////////////////////////////////////////////////////////////////////////////////
//                                  PSE uart0
////////////////////////////////////////////////////////////////////////////////

    const char *uart0_path = icmGetVlnvString(
        0,    // path (0 if from the product directory)
        0,    // vendor
        0,    // library
        "UartPL011",    // name
        0,    // version
        "pse"     // model
    );

    icmAttrListP uart0_attr = icmNewAttrList();
    icmAddStringAttr(uart0_attr, "variant", "ARM");
    icmAddStringAttr(uart0_attr, "outfile", "arm-uart0.log");
    if(connectARMUartPort) {
        if(autoConsole) {
            icmAddUns64Attr(uart0_attr, "console", 1);
        } else {
            icmAddUns64Attr(uart0_attr, "portnum", uartPort);
        }
        icmAddUns64Attr(uart0_attr, "finishOnDisconnect", 1);
    }
    icmPseP uart0_p = icmNewPSE(
        "arm-uart0",   // name
        uart0_path,   // model
        uart0_attr,   // attrlist
        NULL,   // semihost file
        NULL    // semihost symbol
    );

    icmConnectPSEBus( uart0_p, smbus_b, "bport1", 0, 0x10009000, 0x10009fff);
    if(connectARMUartPort) {
        icmSetPSEdiagnosticLevel(uart0_p, 1);
    }


////////////////////////////////////////////////////////////////////////////////
//                                  PSE uart1
////////////////////////////////////////////////////////////////////////////////

    const char *uart1_path = icmGetVlnvString(
        0,    // path (0 if from the product directory)
        0,    // vendor
        0,    // library
        "UartPL011",    // name
        0,    // version
        "pse"     // model
    );

    icmAttrListP uart1_attr = icmNewAttrList();
    icmAddStringAttr(uart1_attr, "variant", "ARM");
    icmAddStringAttr(uart1_attr, "outfile", "arm-uart1.log");

    icmPseP uart1_p = icmNewPSE(
        "arm-uart1",   // name
        uart1_path,   // model
        uart1_attr,   // attrlist
        NULL,   // semihost file
        NULL    // semihost symbol
    );

    icmConnectPSEBus( uart1_p, smbus_b, "bport1", 0, 0x1000a000, 0x1000afff);


////////////////////////////////////////////////////////////////////////////////
//                                  PSE uart2
////////////////////////////////////////////////////////////////////////////////

    const char *uart2_path = icmGetVlnvString(
        0,    // path (0 if from the product directory)
        0,    // vendor
        0,    // library
        "UartPL011",    // name
        0,    // version
        "pse"     // model
    );

    icmAttrListP uart2_attr = icmNewAttrList();

    icmAddStringAttr(uart2_attr, "variant", "ARM");

    icmPseP uart2_p = icmNewPSE(
        "arm-uart2",   // name
        uart2_path,   // model
        uart2_attr,   // attrlist
        NULL,   // semihost file
        NULL    // semihost symbol
    );

    icmConnectPSEBus( uart2_p, smbus_b, "bport1", 0, 0x1000b000, 0x1000bfff);


////////////////////////////////////////////////////////////////////////////////
//                                  PSE uart3
////////////////////////////////////////////////////////////////////////////////

    const char *uart3_path = icmGetVlnvString(
        0,    // path (0 if from the product directory)
        0,    // vendor
        0,    // library
        "UartPL011",    // name
        0,    // version
        "pse"     // model
    );

    icmAttrListP uart3_attr = icmNewAttrList();

    icmAddStringAttr(uart3_attr, "variant", "ARM");

    icmPseP uart3_p = icmNewPSE(
        "arm-uart3",   // name
        uart3_path,   // model
        uart3_attr,   // attrlist
        NULL,   // semihost file
        NULL    // symbol
    );
    icmConnectPSEBus( uart3_p, smbus_b, "bport1", 0, 0x1000c000, 0x1000cfff);


////////////////////////////////////////////////////////////////////////////////
//                                  PSE wdt1
////////////////////////////////////////////////////////////////////////////////

    const char *wdt1_path = icmGetVlnvString(
        0,    // path (0 if from the product directory)
        0,    // vendor
        0,    // library
        "WdtSP805",    // name
        0,    // version
        "pse"     // model
    );

    icmAttrListP wdt1_attr = icmNewAttrList();


    icmPseP wdt1_p = icmNewPSE(
        "wdt1",   // name
        wdt1_path,   // model
        wdt1_attr,   // attrlist
        0,   // semihost file
        0    // semihost symbol
    );

    icmConnectPSEBus( wdt1_p, smbus_b, "bport1", 0, 0x1000f000, 0x1000ffff);


////////////////////////////////////////////////////////////////////////////////
//                                 PSE timer01
////////////////////////////////////////////////////////////////////////////////

    const char *timer01_path = icmGetVlnvString(
        0,    // path (0 if from the product directory)
        0,    // vendor
        0,    // library
        "TimerSP804",    // name
        0,    // version
        "pse"     // model
    );

    icmAttrListP timer01_attr = icmNewAttrList();


    icmPseP timer01_p = icmNewPSE(
        "timer01",   // name
        timer01_path,   // model
        timer01_attr,   // attrlist
        0,   // semihost file
        0    // semihost symbol
    );

    icmConnectPSEBus( timer01_p, smbus_b, "bport1", 0, 0x10011000, 0x10011fff);


////////////////////////////////////////////////////////////////////////////////
//                                 PSE timer23
////////////////////////////////////////////////////////////////////////////////

    const char *timer23_path = icmGetVlnvString(
        0,    // path (0 if from the product directory)
        0,    // vendor
        0,    // library
        "TimerSP804",    // name
        0,    // version
        "pse"     // model
    );

    icmAttrListP timer23_attr = icmNewAttrList();


    icmPseP timer23_p = icmNewPSE(
        "timer23",   // name
        timer23_path,   // model
        timer23_attr,   // attrlist
        0,   // semihost file
        0    // semihost symbol
    );

    icmConnectPSEBus( timer23_p, smbus_b, "bport1", 0, 0x10012000, 0x10012fff);


////////////////////////////////////////////////////////////////////////////////
//                                  PSE dvi1
////////////////////////////////////////////////////////////////////////////////

    const char *dvi1_path = icmGetVlnvString(
        0,    // path (0 if from the product directory)
        0,    // vendor
        0,    // library
        "SerBusDviRegs",    // name
        0,    // version
        "pse"     // model
    );

    icmAttrListP dvi1_attr = icmNewAttrList();


    icmPseP dvi1_p = icmNewPSE(
        "dvi1",   // name
        dvi1_path,   // model
        dvi1_attr,   // attrlist
        0,   // semihost file
        0    // semihost symbol
    );

    icmConnectPSEBus( dvi1_p, smbus_b, "bport1", 0, 0x10016000, 0x10016fff);


////////////////////////////////////////////////////////////////////////////////
//                                  PSE rtc1
////////////////////////////////////////////////////////////////////////////////

    const char *rtc1_path = icmGetVlnvString(
        0,    // path (0 if from the product directory)
        0,    // vendor
        0,    // library
        "RtcPL031",    // name
        0,    // version
        "pse"     // model
    );

    icmAttrListP rtc1_attr = icmNewAttrList();


    icmPseP rtc1_p = icmNewPSE(
        "rtc1",   // name
        rtc1_path,   // model
        rtc1_attr,   // attrlist
        0,   // semihost file
        0    // semihost symbol
    );

    icmConnectPSEBus( rtc1_p, smbus_b, "bport1", 0, 0x10017000, 0x10017fff);


////////////////////////////////////////////////////////////////////////////////
//                                   PSE cf1
////////////////////////////////////////////////////////////////////////////////

    const char *cf1_path = icmGetVlnvString(
        0,    // path (0 if from the product directory)
        0,    // vendor
        0,    // library
        "CompactFlashRegs",    // name
        0,    // version
        "pse"     // model
    );

    icmAttrListP cf1_attr = icmNewAttrList();


    icmPseP cf1_p = icmNewPSE(
        "cf1",   // name
        cf1_path,   // model
        cf1_attr,   // attrlist
        0,   // semihost file
        0    // semihost symbol
    );

    icmConnectPSEBus( cf1_p, smbus_b, "bport1", 0, 0x1001a000, 0x1001afff);


////////////////////////////////////////////////////////////////////////////////
//                                  PSE lcd1
////////////////////////////////////////////////////////////////////////////////

    const char *lcd1_path = icmGetVlnvString(
        0,    // path (0 if from the product directory)
        0,    // vendor
        0,    // library
        "LcdPL110",    // name
        0,    // version
        "pse"     // model
    );

    icmAttrListP lcd1_attr = icmNewAttrList();

//    icmAddUns64Attr(lcd1_attr, "scanDelay", 50000);
    icmAddUns64Attr(lcd1_attr, "noGraphics", noGraphics);
    icmAddStringAttr(lcd1_attr, "resolution", "xga");

    icmPseP lcd1_p = icmNewPSE(
        "lcd1",   // name
        lcd1_path,   // model
        lcd1_attr,   // attrlist
        0,   // semihost file
        "modelAttrs"    // semihost symbol
    );

    icmConnectPSEBus( lcd1_p, smbus_b, "bport1", 0, 0x10020000, 0x10020fff);

    icmConnectPSEBusDynamic( lcd1_p, smbus_b, "memory", 0);


////////////////////////////////////////////////////////////////////////////////
//                                    lcd2
////////////////////////////////////////////////////////////////////////////////


    // Versatile Express contains CLCD controller on both the motherboard and
    // daughterboard.  Rather than 2 instances, map motherboard controller as RAM
    icmMemoryP lcd2_m = icmNewMemory("lcd2_m", 0x7, 0xfff);
    icmConnectMemoryToBus( smbus_b, "sp1", lcd2_m, 0x1001f000);


////////////////////////////////////////////////////////////////////////////////
//                                  PSE dmc1
////////////////////////////////////////////////////////////////////////////////

    const char *dmc1_path = icmGetVlnvString(
        0,    // path (0 if from the product directory)
        0,    // vendor
        0,    // library
        "DMemCtrlPL341",    // name
        0,    // version
        "pse"     // model
    );

    icmAttrListP dmc1_attr = icmNewAttrList();


    icmPseP dmc1_p = icmNewPSE(
        "dmc1",   // name
        dmc1_path,   // model
        dmc1_attr,   // attrlist
        0,   // semihost file
        0    // semihost symbol
    );

    icmConnectPSEBus( dmc1_p, smbus_b, "bport1", 0, 0x100e0000, 0x100e0fff);


////////////////////////////////////////////////////////////////////////////////
//                                  PSE smc1
////////////////////////////////////////////////////////////////////////////////

    const char *smc1_path = icmGetVlnvString(
        0,    // path (0 if from the product directory)
        0,    // vendor
        0,    // library
        "SMemCtrlPL354",    // name
        0,    // version
        "pse"     // model
    );

    icmAttrListP smc1_attr = icmNewAttrList();


    icmPseP smc1_p = icmNewPSE(
        "smc1",   // name
        smc1_path,   // model
        smc1_attr,   // attrlist
        0,   // semihost file
        0    // semihost symbol
    );

    icmConnectPSEBus( smc1_p, smbus_b, "bport1", 0, 0x100e1000, 0x100e1fff);


////////////////////////////////////////////////////////////////////////////////
//                                 PSE timer45
////////////////////////////////////////////////////////////////////////////////

    const char *timer45_path = icmGetVlnvString(
        0,    // path (0 if from the product directory)
        0,    // vendor
        0,    // library
        "TimerSP804",    // name
        0,    // version
        "pse"     // model
    );

    icmAttrListP timer45_attr = icmNewAttrList();


    icmPseP timer45_p = icmNewPSE(
        "timer45",   // name
        timer45_path,   // model
        timer45_attr,   // attrlist
        0,   // semihost file
        0    // semihost symbol
    );

    icmConnectPSEBus( timer45_p, smbus_b, "bport1", 0, 0x100e4000, 0x100e4fff);


////////////////////////////////////////////////////////////////////////////////
//                                PSE eth0
////////////////////////////////////////////////////////////////////////////////

    const char *eth0_path = icmGetVlnvString(
        0,    // path (0 if from the product directory)
        "smsc.ovpworld.org",    // vendor
        "peripheral",           // library
        "LAN9118",              // name
        "1.0",                  // version
        "pse"                   // model
    );

    icmAttrListP eth0_attr = icmNewAttrList();

    icmPseP eth0_p = icmNewPSE(
        "eth0",   // name
        eth0_path,   // model
        eth0_attr,   // attrlist
        0,   // semihost file
        0    // semihost symbol
    );

    icmConnectPSEBus( eth0_p, smbus_b, "bport1", 0, 0x4e000000, 0x4e000fff);

////////////////////////////////////////////////////////////////////////////////
//                                PSE usb0
////////////////////////////////////////////////////////////////////////////////

    const char *usb0_path = icmGetVlnvString(
        0,    // path (0 if from the product directory)
        "philips.ovpworld.org",    // vendor
        "peripheral",           // library
        "ISP1761",    // name
        0,    // version
        "pse"     // model
    );
    icmAttrListP usb0_attr = icmNewAttrList();

    icmPseP usb0_p = icmNewPSE(
        "usb0",   // name
        usb0_path,   // model
        usb0_attr,   // attrlist
        0,   // semihost file
        0    // semihost symbol
    );

    icmConnectPSEBus( usb0_p, smbus_b, "bport1", 0, 0x4f000000, 0x4f00ffff);

   // icmMemoryP m4_m = icmNewMemory("m4_m", 0x7, 0xfff);
   // icmConnectMemoryToBus( smbus_b, "sp1", m4_m, 0x4e000000);

   // icmMemoryP m5_m = icmNewMemory("m5_m", 0x7, 0xfff);
   // icmConnectMemoryToBus( smbus_b, "sp1", m5_m, 0x4f000000);

////////////////////////////////////////////////////////////////////////////////
//                                Memory nor0
////////////////////////////////////////////////////////////////////////////////

    // NOR Flash 0
    icmMemoryP nor0_m = icmNewMemory("nor0_m", ICM_PRIV_RW, 0x03ffffff);
    icmConnectMemoryToBus( smbus_b, "sp1", nor0_m, 0x40000000);

////////////////////////////////////////////////////////////////////////////////
//                                Memory nor1
////////////////////////////////////////////////////////////////////////////////

    // NOR Flash 1
    icmMemoryP nor1_m = icmNewMemory("nor1_m", ICM_PRIV_RW, 0x03ffffff);
    icmConnectMemoryToBus( smbus_b, "sp1", nor1_m, 0x44000000);


////////////////////////////////////////////////////////////////////////////////
//                                Memory sram1
////////////////////////////////////////////////////////////////////////////////

    icmMemoryP sram1_m = icmNewMemory("sram1_m", 0x7, 0x1ffffff);

    icmConnectMemoryToBus( smbus_b, "sp1", sram1_m, 0x48000000);


////////////////////////////////////////////////////////////////////////////////
//                                Memory vram1
////////////////////////////////////////////////////////////////////////////////

    icmMemoryP vram1_m = icmNewMemory("vram1_m", 0x7, 0x7fffff);

    icmConnectMemoryToBus( smbus_b, "sp1", vram1_m, 0x4c000000);


////////////////////////////////////////////////////////////////////////////////
//                               Memory ddr2ram
////////////////////////////////////////////////////////////////////////////////

    icmMemoryP ddr2ram_m = icmNewMemory("ddr2ram_m", 0x7, 0x3fffffff);

    icmConnectMemoryToBus( ddr2bus_b, "sp1", ddr2ram_m, 0x0);


////////////////////////////////////////////////////////////////////////////////
//                            Bridge ddr2RamBridge
////////////////////////////////////////////////////////////////////////////////

    icmNewBusBridge(smbus_b, ddr2bus_b, "ddr2RamBridge", "sp", "mp", 0x0, 0x3fffffff, 0x60000000);


////////////////////////////////////////////////////////////////////////////////
//                           Bridge ddr2RemapBridge
////////////////////////////////////////////////////////////////////////////////

    icmNewBusBridge(smbus_b, ddr2bus_b, "ddr2RemapBridge", "sp1", "mp", 0x20000000, 0x23ffffff, 0x0);


    ////////////////////////////////////////////////////////////////////////////////
    //                                 PSE l2regs
    ////////////////////////////////////////////////////////////////////////////////

        const char *l2regs_path = icmGetVlnvString(
            0,    // path (0 if from the product directory)
            0,    // vendor
            0,    // library
            "L2CachePL310",    // name
            0,    // version
            "pse"     // model
        );

        icmAttrListP l2regs_attr = icmNewAttrList();


        icmPseP l2regs_p = icmNewPSE(
            "l2regs",   // name
            l2regs_path,   // model
            l2regs_attr,   // attrlist
            0,   // semihost file
            0    // semihost symbol
        );

        icmConnectPSEBus( l2regs_p, smbus_b, "bport1", 0, 0x1e00a000, 0x1e00afff);


////////////////////////////////////////////////////////////////////////////////
//                               PSE smartLoader
////////////////////////////////////////////////////////////////////////////////

    const char *smartLoader_path = icmGetVlnvString(
        0,    // path (0 if from the product directory)
        "arm.ovpworld.org",    // vendor
        0,    // library
        "SmartLoaderArmLinux",    // name
        "1.0",    // version
        "pse"     // model
    );

    icmAttrListP smartLoader_attr = icmNewAttrList();

    icmAddStringAttr(smartLoader_attr, "kernel", "zImage");
    icmAddStringAttr(smartLoader_attr, "initrd", "fs.img");

    char command[256] = "mem=1024M raid=noautodetect console=ttyAMA0,38400n8 vmalloc=256MB devtmpfs.mount=0";
    icmAddStringAttr(smartLoader_attr, "command", command);
    icmAddUns64Attr(smartLoader_attr, "memsize", (256*1024*1024));
    icmAddUns64Attr(smartLoader_attr, "physicalbase", 0x60000000);
    icmAddUns64Attr(smartLoader_attr, "boardid", 0x8e0); // Versatile Express
    if(loadBootCode ) {
        icmImagefileP image = icmLoadBus(smbus_b,bootCode,ICM_LOAD_VERBOSE,True);
        if (image) {
            icmAddUns64Attr (smartLoader_attr, "bootaddr", icmGetImagefileEntry(image));
        }
    }


    icmPseP smartLoader_p = icmNewPSE(
        "smartLoader",   // name
        smartLoader_path,   // model
        smartLoader_attr,   // attrlist
        0,   // semihost file
        0    // semihost symbol
    );

    icmConnectPSEBus( smartLoader_p, smbus_b, "mport", 1, 0x0, 0xffffffff);

    // Listed as "Reserved" in data sheet, is used for gpio
    icmMemoryP gpio_m = icmNewMemory("gpio_m", 0x7, 0xfff);
    icmConnectMemoryToBus( smbus_b, "sp1", gpio_m, 0x100e8000);

////////////////////////////////////////////////////////////////////////////////
//                                 CONNECTIONS
////////////////////////////////////////////////////////////////////////////////


    icmNetP cardin_n = icmNewNet("cardin_n" );

    icmConnectPSENet( sysRegs_p, cardin_n, "cardin", ICM_INPUT);

    icmConnectPSENet( mmc1_p, cardin_n, "cardin", ICM_OUTPUT);

////////////////////////////////////////////////////////////////////////////////

    icmNetP wprot_n = icmNewNet("wprot_n" );

    icmConnectPSENet( sysRegs_p, wprot_n, "wprot", ICM_INPUT);

    icmConnectPSENet( mmc1_p, wprot_n, "wprot", ICM_OUTPUT);

////////////////////////////////////////////////////////////////////////////////

    icmNetP ir2_n = icmNewNet("ir2_n" );

    icmConnectProcessorNet( cpu_c, ir2_n, "SPI34", ICM_INPUT);

    icmConnectPSENet( timer01_p, ir2_n, "irq", ICM_OUTPUT);

////////////////////////////////////////////////////////////////////////////////
    icmNetP ir3_n = icmNewNet("ir3_n" );

    icmConnectProcessorNet( cpu_c, ir3_n, "SPI35", ICM_INPUT);

    icmConnectPSENet( timer23_p, ir3_n, "irq", ICM_OUTPUT);

////////////////////////////////////////////////////////////////////////////////
    icmNetP ir4_n = icmNewNet("ir4_n" );

    icmConnectProcessorNet( cpu_c, ir4_n, "SPI36", ICM_INPUT);

    icmConnectPSENet( rtc1_p, ir4_n, "irq", ICM_OUTPUT);

////////////////////////////////////////////////////////////////////////////////
    icmNetP ir5_n = icmNewNet("ir5_n" );

    icmConnectProcessorNet( cpu_c, ir5_n, "SPI37", ICM_INPUT);

    icmConnectPSENet( uart0_p, ir5_n, "irq", ICM_OUTPUT);

////////////////////////////////////////////////////////////////////////////////
    icmNetP ir6_n = icmNewNet("ir6_n" );

    icmConnectProcessorNet( cpu_c, ir6_n, "SPI38", ICM_INPUT);

    icmConnectPSENet( uart1_p, ir6_n, "irq", ICM_OUTPUT);

////////////////////////////////////////////////////////////////////////////////
    icmNetP ir7_n = icmNewNet("ir7_n" );

    icmConnectProcessorNet( cpu_c, ir7_n, "SPI39", ICM_INPUT);

    icmConnectPSENet( uart2_p, ir7_n, "irq", ICM_OUTPUT);

////////////////////////////////////////////////////////////////////////////////
    icmNetP ir8_n = icmNewNet("ir8_n" );

    icmConnectProcessorNet( cpu_c, ir8_n, "SPI40", ICM_INPUT);

    icmConnectPSENet( uart3_p, ir8_n, "irq", ICM_OUTPUT);

////////////////////////////////////////////////////////////////////////////////
    icmNetP ir9_n = icmNewNet("ir9_n" );

    icmConnectProcessorNet( cpu_c, ir9_n, "SPI41", ICM_INPUT);

    icmConnectPSENet( mmc1_p, ir9_n, "irq0", ICM_OUTPUT);

////////////////////////////////////////////////////////////////////////////////
    icmNetP ir10_n = icmNewNet("ir10_n" );

    icmConnectProcessorNet( cpu_c, ir10_n, "SPI42", ICM_INPUT);

    icmConnectPSENet( mmc1_p, ir10_n, "irq1", ICM_OUTPUT);

////////////////////////////////////////////////////////////////////////////////
    icmNetP ir12_n = icmNewNet("ir12_n" );

    icmConnectProcessorNet( cpu_c, ir12_n, "SPI44", ICM_INPUT);

    icmConnectPSENet( kb1_p, ir12_n, "irq", ICM_OUTPUT);

////////////////////////////////////////////////////////////////////////////////
    icmNetP ir13_n = icmNewNet("ir13_n" );

    icmConnectProcessorNet( cpu_c, ir13_n, "SPI45", ICM_INPUT);

    icmConnectPSENet( ms1_p, ir13_n, "irq", ICM_OUTPUT);

////////////////////////////////////////////////////////////////////////////////
    icmNetP ir15_n = icmNewNet("ir15_n" );

    icmConnectProcessorNet( cpu_c, ir15_n, "SPI47", ICM_INPUT);

    icmConnectPSENet( eth0_p, ir15_n, "irq", ICM_OUTPUT);

////////////////////////////////////////////////////////////////////////////////
   icmNetP ir16_n = icmNewNet("ir16_n" );

   icmConnectProcessorNet( cpu_c, ir16_n, "SPI48", ICM_INPUT);

   icmConnectPSENet( usb0_p, ir16_n, "hc_irq", ICM_OUTPUT);

////////////////////////////////////////////////////////////////////////////////
    icmNetP ir44_n = icmNewNet("ir44_n" );

    icmConnectProcessorNet( cpu_c, ir44_n, "SPI76", ICM_INPUT);

    icmConnectPSENet( lcd1_p, ir44_n, "irq", ICM_OUTPUT);

////////////////////////////////////////////////////////////////////////////////
    icmNetP ir48_n = icmNewNet("ir48_n" );

    icmConnectProcessorNet( cpu_c, ir48_n, "SPI80", ICM_INPUT);

    icmConnectPSENet( timer45_p, ir48_n, "irq", ICM_OUTPUT);

////////////////////////////////////////////////////////////////////////////////

    icmIterAllChildren(cpu_c, setStartAddress, 0);

}