files {
    "sim", "conf", "cache", "OS", "mem", "net", "ipi",
    "dmcache", "cpfs", "iopfs", "message", 
    "disk", "diskmodel", "file", "userdata", "lu", "dummy"
}

menu top {
    choice MENU_NET "Network Menu" {
	   display(net_top) 
    },
    choice MENU_DMCACHE_PARMS "DMCACHE Parameters" {
	   display(dmcache_parms),
	   display(disk_choice)
    },
    choice MENU_DMCACHE_CACHE "DMCACHE Caching" {
	   display(cp_cache)
    }
}

menu net_top {
    choice BUS "Bus Based" {
	set(YESCACHE),
	clear(NOCACHE),
	clear(SEND_RECEIVE),
	display(bus),
     display(dmcache)},
    choice NET "Network Based" {
     set(MULT_RL),
	clear(SINGLE_RL),
	clear(NOBUSY),
     display(net)}
}

menu bus {
    choice SINGLE_RL "Single Ready List" {
	display(proc),
	display(busparam),
	display(memory),
	display(cache)},
    choice MULT_RL "Multiple Ready Lists" { 
	display(proc),
	display(busparam),
	display(memory),
	display(cache)}
}

param busparam {
    NO_OF_MODULES "Number of Memory Modules" [1, 1024],
}

menu net {
    choice N_DIRECT "Direct Network" {
	set(NO_OF_PROCESSORS, Nk ^ Ndim),
	set(NO_OF_MODULES, NO_OF_PROCESSORS),
    	set(MAX_PROC_THREADS, 
		2 + (NO_OF_PROCESSORS-2) * NO_OF_DISKS * (1+MAX_OUTSTANDING)),
    	set(MAX_THREADS, (NO_OF_PROCESSORS-2) + 
	    ((NO_OF_PROCESSORS-2) * (MAX_OUTSTANDING+1) + 1) * NO_OF_DISKS),
    	set(MAX_STKBLKS, MAX_THREADS * 3),
	display(direct)},
    choice N_INDIRECT "Indirect Network" {
	clear(NET_EXACT),
	display(cache_indir)}
}

param proc {
    NO_OF_PROCESSORS "Number of Processors" [1, 1024]
}

menu direct {
    choice N_UNIDIR "Unidirectional" {
	display(cache_direct)},
    choice N_BIDIR "Bidirectional" {
	display(cache_direct)}
}

menu cache_direct {
    choice YESCACHE "Use Caches" {
	display(directparam),
	display(memory),
        display(cache)},
    choice NOCACHE "No caches" {
	display(directparam),
	display(memory)}
}

menu cache_indir {
    choice YESCACHE "Use Caches" {
	display(indirparam),
	display(memory),
        display(cache)},
    choice NOCACHE "No caches" {
	display(indirparam),
	display(memory)}
}

param directparam {
    Nk "k-ary Radix" [1, 1024]
	{ set(NO_OF_PROCESSORS, Nk ^ Ndim),
	  set(NO_OF_MODULES, NO_OF_PROCESSORS),
    	set(MAX_PROC_THREADS, 
		2 + (NO_OF_PROCESSORS-2) * NO_OF_DISKS * (1+MAX_OUTSTANDING)),
    	set(MAX_THREADS, (NO_OF_PROCESSORS-2) + 
	    ((NO_OF_PROCESSORS-2) * (MAX_OUTSTANDING+1) + 1) * NO_OF_DISKS),
    	set(MAX_STKBLKS, MAX_THREADS * 3)
    },
    Ndim "n-cube Dimension" [1, 10]
        { set(NO_OF_PROCESSORS, Nk ^ Ndim),
	  set(NO_OF_MODULES, NO_OF_PROCESSORS),
    	set(MAX_PROC_THREADS, 
		2 + (NO_OF_PROCESSORS-2) * NO_OF_DISKS * (1+MAX_OUTSTANDING)),
    	set(MAX_THREADS, (NO_OF_PROCESSORS-2) + 
	    ((NO_OF_PROCESSORS-2) * (MAX_OUTSTANDING+1) + 1) * NO_OF_DISKS),
    	set(MAX_STKBLKS, MAX_THREADS * 3)
    },
    watch "Number of Processors:" (NO_OF_PROCESSORS),
    MAX_PACKET_WORDS "Packet Length in Words" [3, 10240],
    SWITCH_DELAY "Switch Delay" [0, 64],
    WIRE_DELAY "Wire Delay" [0, 16],
    NET_EXACT "Exact Simulation",
    ALEWIFE "Alewife Version",
    SEND_RECEIVE "Sync. Send/Receive",
    PARAGON "Paragon-like network"
}

param indirparam {
    NO_OF_PROCESSORS "Number of Processors" [1, 1024]
	{ set(NO_OF_MODULES, NO_OF_PROCESSORS),
    	set(MAX_PROC_THREADS, 
		2 + (NO_OF_PROCESSORS-2) * NO_OF_DISKS * (1+MAX_OUTSTANDING)),
    	set(MAX_THREADS, (NO_OF_PROCESSORS-2) + 
	    ((NO_OF_PROCESSORS-2) * (MAX_OUTSTANDING+1) + 1) * NO_OF_DISKS),
    	set(MAX_STKBLKS, MAX_THREADS * 3)
    },
    NET_STAGES "Number of Stages" [2, 8],
    MAX_PACKET_WORDS "Packet Length in Words" [3, 10240],
    SWITCH_DELAY "Switch Delay" [0, 64],
    WIRE_DELAY "Wire Delay" [0, 16]
}

menu OS {
    choice SCHED_FCFS "FCFS Scheduler" {
	display(OSsem)},
    choice SCHED_SIMPLE  "Round-robin Scheduler" {
	display(OSsem)},
    choice SCHED_PRIORITY  "Priority-flow Scheduler" {
	display(OSsem)}
}

menu OSsem {
    choice SEMA_TTSET "TTSET Semaphores" {
	display(OSspin),
	display(OSparam)},
    choice SEMA_FEBIT "F/E Semaphores" {
	display(OSparam)},
    choice SEMA_USER "User Semaphores" {
        display(OSparam)}
}

param OSspin {
    TTSET_DELAY "TTSET backoff delay" [0, 32000]
}

param OSparam {
    OS_QUANTUM "Operating System Quantum" [1000, 10000],
    USERMAIN_STACK "usermain stack blocks" [4, 256],
    OS_CALL_PRIORITY "Ihandler Priority",
    RANDOMREQ "Use Random Seed",
    FATAL "Fatal error in OS calls",
    TIMER_PERIOD "Timer Interrupt Period",
    NOBUSY "No busy waiting (for ttset)"
}

param cache {
    CACHE_BITS "Bits in Cache Size" [4, 12],
    LINE_BITS  "Bits in Line Size" [1, 6],
    SET_SIZE "Set Size" [1, 8],
    watch "Total Cache Size:" (SET_SIZE * 2^(CACHE_BITS + LINE_BITS)),
    CACHEWITHDATA "Software Coherence"
}

param memory {
    MODULE_BITS "Bits in Memory Size" [4, 16],
    watch "Memory Modules:" (NO_OF_MODULES)
}

param simulator {
    SIM_QUANTUM "Simulator Quantum" [1, 4096],
    watch "Thread Count Limit:" (MAX_THREADS),
    STK_BLK_SIZE "Stack Block Size" [512, 8192],
    STK_THRESHOLD "Stack Overflow Threshold" [256, 2048],
    watch "Stack Block Pool Size:" (MAX_STKBLKS),
    MAX_SIMREQS "Simulator Request Limit" [64, 2048],
    MAX_INTR_TYPES "Maximum Interrupt Types" [16, 1024],
    INTR_PER_PROCESSOR "Maximum Pending Interrupts" [4, 100],
    MAX_SEMAPHORES "Maximum Number of Semaphores" [16, 16384],
    MAX_PACKETS "Maximum Number of Packets" [128, 8192]
}

param statistics {
    WATCH_USER "Watch User Events",
    WATCH_CACHE "Watch Cache Events",
    WATCH_THREADS "Watch Thread Events",
    WATCH_IDLE "Watch Idle Events",
    WATCH_SEM "Watch Semaphore Events",
    WATCH_BUS "Watch bus contention",
    WATCH_NET "Watch net contention"
}

param latencies {
    MEM_ACCESS_LATENCY "Memory Access",
    CACHE_ACCESS_LATENCY "Cache Access",
    RESCHEDULE_LATENCY "Reschedule",
    INTR_LATENCY "Interrupt"
}

param dmcache_parms {
    REAL_DATA "Move real data, not fake data",
    TICSperSEC "Cycles per second" [1000000,200000000]
    {	set (BYTESperFLIT, BYTESperSEC / TICSperSEC)    },
    BYTESperSEC "Routing bandwidth, bytes per second" [100000,500000000]
    {	set (BYTESperFLIT, BYTESperSEC / TICSperSEC)    },
    watch "Flit size (bytes):" (BYTESperFLIT),
    TRAP_CYCLES "Syscall overhead, in cycles" [0,1000],
    NET_SCATTER_GATHER "Network chip supports scatter/gather",
    LOG_BLOCK_SIZE "Disk block-size bits" [8,16] {
      set (BLOCK_SIZE, 2 ^ LOG_BLOCK_SIZE)
    },
    watch "Disk block size:" (BLOCK_SIZE),
    FILE_BLOCKS_MAX "File size in blocks (max)." [1,65536],
    RECORD_SIZE "Record size in bytes, but multiple of 4." 
    	   valid(RECORD_SIZE >= 4),
    LU_MATRIX_SIZE "LU matrix size" [2,5000],
    LU_SLAB_SIZE "LU number of cols in slab" [1,5000] 
	valid (SLAB_SIZE <= LU_MATRIX_SIZE),
    NO_OF_DISKS "Number of disks" [1,1024] {
    	set(MAX_PROC_THREADS, 
		2 + (NO_OF_PROCESSORS-2) * NO_OF_DISKS * (1+MAX_OUTSTANDING)),
    	set(MAX_THREADS, (NO_OF_PROCESSORS-2) + 
	    ((NO_OF_PROCESSORS-2) * (MAX_OUTSTANDING+1) + 1) * NO_OF_DISKS),
    	set(MAX_STKBLKS, MAX_THREADS * 3)
    },
    DISK_FCFS "FCFS disk schedule"
}

menu disk_choice {
    choice TRIVIAL_DISK "Trivial disk" {
    	    clear(HP97560),
    	    display(trivial_disk),
    	    display(layout) },
    choice MODEL_DISK "Real disk model" {
    	    set(HP97560),
    	    display(model_disk),
    	    display(layout) },
}

menu layout {
    choice LAYOUT_CONTIGUOUS "Lay out blocks contiguously" { },
    choice LAYOUT_RANDOM_SECTORS "Lay out blocks on random sectors" { },
    choice LAYOUT_RANDOM_TRACKS "Lay out blocks on random tracks" { }
}

param model_disk {
    DISK_RAND_ROT "Disk rot. position starts random."
}

param trivial_disk {
    DISK_READ_TIME "Disk read time (msec)." [1,100],
    DISK_WRITE_TIME "Disk write time (msec)." [1,100],
    DISK_NSECTORS "Number of sectors." [1,10000000],
    DISK_SECTOR_SIZE "Sector size (power of 2)." [256,8192]
}

menu cp_cache {
    choice CP_NONE "None" {
	   display(cp_parms),
	   display(iop_cache) },
    choice CP_SINGLE "Single" {
	   display(cp_parms),
	   display(iop_cache) },
    choice CP_DOUBLE "Double" {
	   display(cp_parms),
	   display(iop_cache) },
    choice CP_THREAD "Thread" {
	   display(cp_parms),
	   display(iop_cache) },
    choice CP_DIRECT "Disk-directed" { 
    	    set(IOP_NONE, 0),
    	    set(IOP_BUFFER, 0),
    	    set(IOP_CACHE, 0),
	   display(cp_parms),
	   display(iop_cache) }
}

param cp_parms {
    CP_MEMGET_WRITES "CPFS uses IOPwrite_memget",
    USE_QUEUE_REQUESTS "Use QueueRequest instead of ThreadRequest"
}

menu iop_cache {
    choice IOP_NONE "None" { display(prefetch) },
    choice IOP_BUFFER "Buffer" { display(prefetch) },
    choice IOP_CACHE "Cache" { 
	display(prefetch), display(twophase), display(consistency) },
    choice IOP_GENERAL "Disk-directed, general" { 
	set(TWO_PHASE, 0), display(general) }
}

param prefetch {
    IOP_AHEAD_BEHIND "Disk read ahead and write behind",
    MAX_OUTSTANDING "Maximum outstanding CP->IOP requests, per CP per disk" [1,100] {
    	set(MAX_PROC_THREADS, 
		2 + (NO_OF_PROCESSORS-2) * NO_OF_DISKS * (1+MAX_OUTSTANDING)),
    	set(MAX_THREADS, (NO_OF_PROCESSORS-2) + 
	    ((NO_OF_PROCESSORS-2) * (MAX_OUTSTANDING+1) + 1) * NO_OF_DISKS),
    	set(MAX_STKBLKS, MAX_THREADS * 3)
	}
}

param twophase {
    TWO_PHASE "Use two-phase I/O",
    MEMPUT_QUEUED "Use Memputq and Memgetq"
}

param general {
    DISK_SORT "Sort disk requests by sector number",
    FILTER_PERCENT "Percent of requests to filter out" [0, 100],
    MEMPUT_QUEUED "Use Memputq and Memgetq"
}

menu consistency {
    choice CONSISTENCY_NONE "None" { },
    choice CONSISTENCY_SPRITE "Sprite-like" { },
    choice CONSISTENCY_COMBINE "Combining" { }
}

