proc kernel_drc {lib_handle} {
	puts "Kernel DRC ..."
}



proc generate {libname} {
    set processor_type [xget_value $libname "PARAMETER" "processor_type"]
    # puts "proc type is $processor_type\n"
    switch $processor_type {
	"mb" { file copy "./src/Makefile_mb.sh" "./src/Makefile" }
	"ppc"  {file copy "./src/Makefile_ppc.sh" "./src/Makefile"}
	"default" {puts "unknown processor type\n"}
    }

    puts "Generating Kernel Header and Initialization config files - os_config.h, config_init.h"
    set config_file [xopen_new_include_file "./src/include/os_config.h" "XilKernel Configuration parameters"]
    set init_file [xopen_new_include_file  "./src/include/config_init.h" "XilKernel Configuration parameters"]
    xprint_generated_header $init_file "LibXilKernel Initialization structures"
    puts $init_file "\#include <sys/init.h>"
    puts $init_file "\#include <os_config.h>\n\n"

# Create defines and struct initializations
    set config_mutex [xget_value $libname "PARAMETER" "config_mutex"]
    if { $config_mutex == "true" } {
	xadd_define $config_file $libname "config_mutex"
    }

    set config_process [xget_value $libname "PARAMETER" "config_process"]
    if { $config_process == "true" } {
	xadd_define $config_file $libname "config_process"
	xadd_define $config_file $libname "max_procs"
	xadd_define $config_file $libname "max_readyq"
	xadd_define $config_file $libname "config_process_exit"
	xadd_define $config_file $libname "config_process_kill"
	xadd_define $config_file $libname "config_process_sleep"
	xadd_define $config_file $libname "config_process_yield"
	set n_init_process [llength [xget_handle [xget_handle $libname "ARRAY" "process_table"] "ELEMENTS" "*"]]
	xput_define $config_file "n_init_process" $n_init_process

	xadd_struct $init_file $libname "_process_init" "start_p" "process_table" "process_start_addr" "process_prio"
    } 

    set config_sched [xget_value $libname "PARAMETER" "config_sched"]
    if { $config_sched == "true" } {
	xadd_define $config_file $libname "config_sched"
	xadd_define $config_file $libname "sched_type"
	xadd_define $config_file $libname "n_prio"
    }
    
    
    set config_thread [xget_value $libname "PARAMETER" "config_thread_support"]
    if { $config_thread == "true" } {
	xadd_define $config_file $libname "config_thread_support"
	xadd_define $config_file $libname "max_threads"
	xadd_define $config_file $libname "thread_stack_size"
    }

    set config_sema [xget_value $libname "PARAMETER" "config_sema"]
    if { $config_sema == "true" } {
	xadd_define $config_file $libname "config_sema"
	xadd_define $config_file $libname "max_sema"
	xadd_define $config_file $libname "max_sema_waitq"
    

	set config_msgq [xget_value $libname "PARAMETER" "config_msgq"]
	if { $config_msgq == "true" } {
	    xadd_define $config_file $libname "config_msgq"
	    xadd_define $config_file $libname "max_msgsize"
	    xadd_define $config_file $libname "max_msg"
	    set n_msgq [llength [xget_handle [xget_handle $libname "ARRAY" "msgq_table"] "ELEMENTS" "*"]]
	    xput_define $config_file "n_msgq" $n_msgq
	    set msgq_msize [get_field_product_sum $libname "msgq_table"  "msg_size" "msgq_len"]
	    xput_define $config_file "msgq_msize" $msgq_msize
	    xadd_struct $init_file $libname "_msgq_init" "msgq_config" "msgq_table" "msg_size" "msgq_len"
	} 
    }

    set config_shm [xget_value $libname "PARAMETER" "config_shm"]
    if { $config_shm == "true" } {
	xadd_define $config_file $libname "config_shm"
	set n_shm [llength [xget_handle [xget_handle $libname "ARRAY" "shm_table"] "ELEMENTS" "*"]]
	xput_define $config_file "n_shm" $n_shm
	set shm_msize [get_field_sum $libname "shm_table"  "shm_size"]
	xput_define $config_file "shm_msize" $shm_msize

	xadd_struct $init_file $libname "_shm_init" "shm_config" "shm_table" "shm_size"
    }

    set config_malloc [xget_value $libname "PARAMETER" "config_malloc"]
    if { $config_malloc == "true" } {
	xadd_define $config_file $libname "config_malloc"
	set n_malloc_blocks [llength [xget_handle [xget_handle $libname "ARRAY" "mem_table"] "ELEMENTS" "*"]]
	xput_define $config_file "n_malloc_blocks" $n_malloc_blocks
	set tot_malloc_blocks [get_field_sum $libname "mem_table"  "mem_nblks"]
	xput_define $config_file "tot_malloc_blocks" $tot_malloc_blocks

	set malloc_msize [get_field_product_sum $libname "mem_table"  "mem_bsize" "mem_nblks"]
	xput_define $config_file "malloc_msize" $malloc_msize

	xadd_struct $init_file $libname "_malloc_init" "malloc_config" "mem_table" "mem_bsize" "mem_nblks"
    } 

    # complete the header protectors
    puts $config_file "\#endif"
    close $config_file
    puts $init_file "\#endif"
    close $init_file
}


proc execs_generate {libname} {
    puts "Generating the xilkernel executable"
    exec bash -c "cd src; make kernel"
}

proc xopen_new_include_file { filename description } {
    set inc_file [open $filename w]
    xprint_generated_header $inc_file $description
    set newfname [string map {. _} [lindex [split $filename {\/}] end]]
    puts $inc_file "\#ifndef _[string toupper $newfname]"
    puts $inc_file "\#define _[string toupper $newfname]\n\n"
    return $inc_file
}

proc xadd_define { config_file libname parameter } {
    set param_value [xget_value $libname "PARAMETER" $parameter]
    puts $config_file "#define [string toupper $parameter] $param_value\n"

    # puts "creating #define [string toupper $parameter] $param_value\n"
}

proc xput_define { config_file parameter param_value } {
    puts $config_file "#define [string toupper $parameter] $param_value\n"

    # puts "creating #define [string toupper $parameter] $param_value\n"
}


# args is variable no - fields of the array
proc xadd_struct {initfile libhandle structtype structname arrayname args} { 

    set arrhandle [xget_handle $libhandle "ARRAY" $arrayname]
    set elements [xget_handle $arrhandle "ELEMENTS" "*"]
    set count 0
    set max_count [llength $elements]
    puts $initfile "struct $structtype $structname\[$max_count\] = \{"

    foreach ele $elements {
	incr count
	puts -nonewline $initfile "\t\{"
	foreach field $args {
	    set field_value [xget_value $ele "PARAMETER" $field]
	    # puts "$arrayname ( $count )->$field is $field_value"
	    if { $field == [lindex $args end] } {
		puts -nonewline $initfile "$field_value"
	    } else {
		puts -nonewline $initfile "$field_value,"
	    }
	}
	if {$count < $max_count} {
	    puts $initfile "\},"
	} else {
	    puts $initfile "\}"
	}
    }
    puts $initfile "\}\;"
}

# return the sum of all the arg field values in arrayname
proc get_field_sum {libhandle arrayname arg} { 

    set arrhandle [xget_handle $libhandle "ARRAY" $arrayname]
    set elements [xget_handle $arrhandle "ELEMENTS" "*"]
    set count 0
    set max_count [llength $elements]
  
    foreach ele $elements {
	set field_value [xget_value $ele "PARAMETER" $arg]
	set count [expr $field_value+$count]
    }
    return $count
}

# return the sum of the product of field values in arrayname
proc get_field_product_sum {libhandle arrayname field1 field2} { 

    set arrhandle [xget_handle $libhandle "ARRAY" $arrayname]
    set elements [xget_handle $arrhandle "ELEMENTS" "*"]
    set count 0
    set max_count [llength $elements]
  
    foreach ele $elements {
	set field1_value [xget_value $ele "PARAMETER" $field1]
	set field2_value [xget_value $ele "PARAMETER" $field2]
	set incr_value [expr $field1_value*$field2_value]
	set count [expr $count+$incr_value]
    }
    return $count
}
