# 
# $Id$
# 
# [ Description ]
# 
# Makefile
# 

#-----[ Directory ]----------------------------------------
DIR_BIN				= bin
DIR_LIB				= ../lib
DIR_CFG_GEN			= configuration_generated
DIR_CFG_USER			= configuration
DIR_LOG				= log

#-----[ Variables ]----------------------------------------
CFG_FILE_EXTENSION		= cfg
CFG_FILE_DEBUG       		= debug.$(CFG_FILE_EXTENSION)

OBJECTS      			= $(OBJECTS_COMMON)

EXEC_PARAMS 			= $(SYSTEMC_EXEC_PARAMS_$(SIMULATOR))
EXEC_LOG			= $(patsubst $(DIR_CFG_GEN)/%.cfg,$(DIR_LOG)/%.exec.log,$(wildcard $(DIR_CFG_GEN)/*.cfg))	\
				  $(patsubst $(DIR_CFG_USER)/%.cfg,$(DIR_LOG)/%.exec.log,$(wildcard $(DIR_CFG_USER)/*.cfg))
EXEC				= soft

#-----[ Rules ]--------------------------------------------
.PRECIOUS			: $(DIR_BIN)/%.x $(DIR_LOG)/%.exec.log
#.NOTPARALLEL			: clean clean_all help

all_selftest   			: test_env $(DIR_OBJ) $(DIR_BIN) $(DIR_LOG)
				@\
				$(MAKE) library;\
				$(MAKE) $(DIR_BIN)/$(EXEC).x;

execute				: all_selftest
				@$(MAKE) $(EXEC_LOG);

reconfig			:
				@\
				$(MAKE) config_clean;\
				$(MAKE) config;

config_clean			:
				@$(RM) $(DIR_CFG_GEN)

config        			: $(DIR_CFG_GEN)
				@\
				$(ECHO) "Generate configuration";									\
				declare -i  CPT=0;											\
				declare     files;											\
																	\
				if $(TEST) -f $(CFG_FILE_DEBUG); then									\
					files=$(CFG_FILE_DEBUG);									\
				else													\
					files=$$($(LS) *.$(CFG_FILE_EXTENSION) );							\
				fi;													\
																	\
				for file in $$files; do											\
																	\
					declare     NAME;										\
					declare -ai MIN ;										\
					declare -ai MAX ;										\
					declare -a  STEP; 										\
					declare -a  LINE; 										\
					declare -ai PERIOD;										\
					declare -a  RANGE;										\
					declare -a  RANGE_LOCAL;									\
					declare -a  SIZE;										\
					declare -i  IT=0; 										\
																	\
					PERIOD[0]=1;											\
																	\
					while read line; do										\
					        LINE=($$line);										\
																	\
						if $(TEST) $$IT -eq 0; then 								\
							NAME=$${LINE[0]};								\
						else											\
							MIN[$$IT]=$${LINE[0]};								\
							MAX[$$IT]=$${LINE[1]};								\
							STEP[$$IT]=$${LINE[2]};								\
							RANGE[$$IT]=$$($(DIR_SCRIPT)/range.sh $${LINE[0]} $${LINE[1]} $${LINE[2]});	\
							RANGE_LOCAL=($${RANGE[$$IT]});							\
							SIZE[$$IT]=$${#RANGE_LOCAL[*]};							\
							PERIOD[$$IT]=$$(($${PERIOD[$$(($$IT-1))]}*$${SIZE[$$IT]}));			\
						fi;											\
																	\
						IT=$$(($$IT+1));									\
					done < $$file;											\
																	\
					declare -i x;											\
					declare -a DATA;										\
					declare -ai ENUM_CONFIG=($$($(DIR_SCRIPT)/range.sh 0 $$(($${PERIOD[$$(($$IT-1))]}-1))));	\
					declare -ai ENUM_PARAM=($$($(DIR_SCRIPT)/range.sh 1 $${#MIN[*]}));            			\
																	\
					$(ECHO) " * File : $$file";									\
 					$(ECHO) "   * They are $${#MIN[*]} parameters";							\
 					$(ECHO) "   * Generate $${PERIOD[$$(($$IT-1))]} configurations";				\
																	\
					for i in $${ENUM_CONFIG[*]}; do									\
						x=$$i;											\
						for j in $${ENUM_PARAM[*]}; do								\
							RANGE_LOCAL=($${RANGE[$$j]});							\
							DATA[$$j]="$${RANGE_LOCAL[$$((($$x % $${SIZE[$$j]})))]} ";			\
							x=$$(($$x/$${SIZE[$$j]})); 							\
						done;											\
						$(ECHO) $${DATA[*]} > "$(DIR_CFG_GEN)/$${NAME}_$$CPT.cfg";				\
						$(ECHO) "   - {$$CPT} $${DATA[*]}";							\
						CPT=$$(($$CPT+1));									\
					done;												\
				done;

$(DIR_LOG)/%.exec.log		: $(DIR_CFG_GEN)/%.cfg  $(DIR_BIN)/$(EXEC).x
				@\
				$(ECHO) "Execute            : $*";\
				export SYSTEMC=$(SYSTEMC_$(SIMULATOR)) ; ./$(DIR_BIN)/$(EXEC).x $(EXEC_PARAMS) $* `$(CAT) $<` &> $@
				declare -i count=`$(GREP) -ch "Test OK" $@`;		\
				declare    timing=`$(GREP) -h "Timing"  $@`;		\
				if $(TEST) $$count -ne 0;       			\
				then echo -e "                     $* ... OK\t$$timing";\
				else echo    "                     $* ... KO"; exit 1;     \
				fi;

$(DIR_LOG)/%.exec.log		: $(DIR_CFG_USER)/%.cfg $(DIR_BIN)/$(EXEC).x
				@\
				$(ECHO) "Execute            : $*";\
				export SYSTEMC=$(SYSTEMC_$(SIMULATOR)) ; ./$(DIR_BIN)/$(EXEC).x $(EXEC_PARAMS) $* `$(CAT) $<` &> $@
				declare -i count=`$(GREP) -ch "Test OK" $@`;		\
				if $(TEST) $$count -ne 0;       			\
				then echo "                     $* ... OK";           	\
				else echo "                     $* ... KO"; exit 1;     \
				fi;

$(DIR_BIN)/%.x			: $(OBJECTS) $(HEADERS) $(DIR_LIB)
				@\
				$(ECHO) "Linkage            : $*";\
				$(CXX) $(LFLAGS) -o $@ $(OBJECTS) $(LIBS);

$(DIR_BIN)			:
				@\
				$(ECHO) "Create directory   : $@";\
				$(MKDIR) $@;

$(DIR_LOG)			:
				@\
				$(ECHO) "Create directory   : $@";\
				$(MKDIR) $@;

$(DIR_CFG_GEN)			:
				@\
				$(ECHO) "Create directory   : $@";\
				$(MKDIR) $@;

selftest_clean_all		: library_clean
				
selftest_clean			: config_clean 
				@$(RM) 	$(DIR_LOG)		\
					$(DIR_CFG_USER)/*~	\
					*.vhdl			\
					*.pos			\
					*.stat			\
					*.dot 			\
					*.txt			\
					generated_by_systemcass \
					core*;

selftest_help			:
				@\
				$(ECHO) " -----[ Selftest ]-----------------------------------";\
				$(ECHO) "";\
				$(ECHO) " * all_selftest         : compile all c++ file and execute";\
				$(ECHO) " * execute              : execute all instance";\
				$(ECHO) " * config               : generate configuration with configuration's file" ;\
				$(ECHO) " * reconfig             : regenerate configuration with configuration's file" ;\
				$(ECHO) " * clean                : Erase all generate files";\
				$(ECHO) " * clean_all            : Clean + Erase all dependant library";\
				$(ECHO) " * help                 : print this text";\
				$(ECHO) "";

help				: 
				@\
				$(MAKE) common_help  ; \
				$(MAKE) synthesis_help;\
				$(MAKE) selftest_help;

clean				: 
				@\
				$(MAKE) common_clean ;\
				$(MAKE) synthesis_clean ;\
				$(MAKE) selftest_clean;

clean_all			: 
				@\
				$(MAKE) clean ;\
				$(MAKE) selftest_clean_all;
