Profiling arm/nds program

support for the ARM toolchain
LeRodeur
Posts: 13
Joined: Tue Jul 31, 2012 2:36 pm

Profiling arm/nds program

Post by LeRodeur » Tue Jul 31, 2012 4:24 pm

Hello,
I wanted to do some profiling on my homebrew, to be able to speed it up a bit.
But when i used -pg command in my makefile, it seemed profiling wasnt implemented in devkitpro. (undefined reference to __gnu_mcount_nc)
I searched the net and bumped into this : http://doc.ironwoodlabs.com/arm-arm-non ... count.html
Would it be possible to implement profiling in devkitarm for the nds? (at least for the arm9)
Or could someone code an implementation for me? I only want for arm9 as my program uses default arm7 core.
I would have done it by myself if I knew how to code in ASM.
Thanks in advance.

mtheall
Posts: 210
Joined: Thu Feb 03, 2011 10:47 pm

Re: Profiling arm/nds program

Post by mtheall » Thu Aug 09, 2012 10:21 pm

I've used the cyg-profiler in the past with the -finstrument-functions option. You can download a stub project from here. I got the information and files from here.

In the Makefile, I added the variable PROFILE so you can easily see the options added.

LeRodeur
Posts: 13
Joined: Tue Jul 31, 2012 2:36 pm

Re: Profiling arm/nds program

Post by LeRodeur » Sun Aug 12, 2012 3:20 pm

thanks a lot, I will give it a try soon!
I forgot that the NDS didn't have a proper clock, using Hblanks seems nice

LeRodeur
Posts: 13
Joined: Tue Jul 31, 2012 2:36 pm

Re: Profiling arm/nds program

Post by LeRodeur » Sat Aug 18, 2012 6:54 pm

I tested it with the files you gave me but the linker tells that there is undefined reference to functions of ulibrary, it only happends when adding the cflags -finstrument-functions -mpoke-function-name
Here is my makefile :

Code: Select all

PATH 		:= $(DEVKITARM)/bin:$(PATH)
#---------------------------------------------------------------------------------
# Please uncomment (i.e. delete the '#') only one "ARM7_SELECTED" line. If unsure,
# leave it as is (with ARM7_MP3 uncommented).
#---------------------------------------------------------------------------------

#MAXMODUSE=YES
#ARM7_SELECTED = ARM7_MP3
#ARM7_SELECTED = ARM7_MP3_DSWIFI
#ARM7_SELECTED = ARM7_MAXMOD_DSWIFI

USE_EFS = YES
LAUNCH_ROM_AFTER_BUILD = YES

#arm7 included with this makefile
#include $(DEVKITPRO)/PAlib/lib/PA_Makefile2
#ARM7BIN		:= -7 $(PAPATH)/lib/arm7/arm7.bin
TEXT1 		:= Diablo Project
TEXT2 		:= using µLib
TEXT3 		:= By Le Rodeur
ICON 			:= -b $(CURDIR)/../logo.bmp

#---------------------------------------------------------------------------------
.SUFFIXES:
#---------------------------------------------------------------------------------
ifeq ($(strip $(DEVKITARM)),)
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM)
endif
#---------------------------------------------------------------------------------
# TARGET is the name of the output, if this ends with _mb generates a multiboot image
# BUILD is the directory where object files & intermediate files will be placed
# SOURCES is a list of directories containing source code
# INCLUDES is a list of directories containing extra header files
#---------------------------------------------------------------------------------
TARGET	:=	$(shell basename $(CURDIR))
BUILD		:=	build
SOURCES	:=	gfx/bin source source/objects source/maps data
INCLUDES	:=	include build data gfx $(BUILD)
DATA		:=	data
AUDIO    	:=  audio

EXPORT_DIR := /c/ndsexamples/
#---------------------------------------------------------------------------------
# ARM7BIN is the path to an arm7 binary other than the default
#	usage: ARM7BIN := -7 binaryName.bin
#
# ICON is the path to an icon to be used int the header plus text
#	usage: ICON := -t iconName.bmp "text line one; text line 2; text line 3"
#
#---------------------------------------------------------------------------------



#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
ARCH	:=	-mthumb-interwork

# note: arm9tdmi isn't the correct CPU arch, but anything newer and LD
# *insists* it has a FPU or VFP, and it won't take no for an answer!
CFLAGS	:=  -finstrument-functions -mpoke-function-name -Wall -O2 \
 		-mcpu=arm9tdmi -mtune=arm9tdmi -fomit-frame-pointer\
		-ffast-math\
		$(ARCH)

CFLAGS	+=	$(INCLUDE) -DARM9 -I$(DEVKITPRO)/PAlib/include/nds

ASFLAGS	:=	-g $(ARCH)
LDFLAGS	:=	-g $(ARCH) -mno-fpu -L$(DEVKITPRO)/PAlib/lib -lpa9


#---------------------------------------------------------------------------------
# path to tools - this can be deleted if you set the path in windows
#---------------------------------------------------------------------------------
# export PATH		:=	/d/dev/ds/devkitARM_r11/bin:/bin

#---------------------------------------------------------------------------------
# PATH to ndslib - just make a system variable called NDSLIBPATH and be done with it
#---------------------------------------------------------------------------------
# NDSLIBPATH	:=	/d/dev/ds/ndslib/

#---------------------------------------------------------------------------------
# the prefix on the compiler executables
#---------------------------------------------------------------------------------
PREFIX			:=	arm-eabi-
#---------------------------------------------------------------------------------
# any extra libraries we wish to link with the project
#---------------------------------------------------------------------------------
LIBS	:= -lul -lfilesystem -lmm9 -lpng -lz -lfat -lnds9


#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
LIBDIRS	:=	$(DEVKITPRO)/libnds


#---------------------------------------------------------------------------------
# no real need to edit anything past this point unless you need to add additional
# rules for different file extensions
#---------------------------------------------------------------------------------
ifneq ($(BUILD),$(notdir $(CURDIR)))
#---------------------------------------------------------------------------------

export OUTPUT	:=	$(CURDIR)/$(TARGET)

export VPATH	:=	$(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
					$(foreach dir,$(DATA),$(CURDIR)/$(dir))
export CC		:=	$(PREFIX)gcc
export CXX		:=	$(PREFIX)g++
export AR		:=	$(PREFIX)ar
export OBJCOPY	:=	$(PREFIX)objcopy
#---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C
#---------------------------------------------------------------------------------
export LD		:=	$(CXX)
#export LD		:=	$(CC)

CFILES		:=	$(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
CPPFILES	:=	$(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
SFILES		:=	$(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
PCXFILES	:=	$(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.pcx)))
BINFILES	:=	$(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.bin)))
PNGFILES	:=	$(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.png)))
PALFILES	:=	$(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.pal)))
RAWFILES	:=	$(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.raw)))
MAPFILES	:=	$(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.map)))
JPEGFILES	:=	$(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.jpg)))
MODFILES	:=	$(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.mod)))
GIFFILES	:=	$(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.gif)))
BMPFILES	:=	$(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.bmp)))


ifeq ($(strip $(MAXMODUSE)), YES)
	export AUDIOFILES := $(foreach file,$(notdir $(wildcard $(AUDIO)/*.mod)),$(CURDIR)/$(AUDIO)/$(file)) \
	                     $(foreach file,$(notdir $(wildcard $(AUDIO)/*.s3m)),$(CURDIR)/$(AUDIO)/$(file)) \
	                     $(foreach file,$(notdir $(wildcard $(AUDIO)/*.xm)),$(CURDIR)/$(AUDIO)/$(file))  \
	                     $(foreach file,$(notdir $(wildcard $(AUDIO)/*.it)),$(CURDIR)/$(AUDIO)/$(file))  \
	                     $(foreach file,$(notdir $(wildcard $(AUDIO)/*.wav)),$(CURDIR)/$(AUDIO)/$(file))

	ifeq ($(strip $(AUDIOFILES)),)
		TEXT_TO_SAY_2 := No Maxmod-compatible files were found in the audio folder.
		TEXT_TO_SAY_3 := If you are loading the soundbank from the filesystem, ignore this message.
		TEXT_TO_SAY_4 := " "
		DONT_BUILD_MAXMOD_SOUNDBANK := YES
	else
		# Add the Maxmod soundbank to the list of bin files
		BINFILES += soundbank_bin.bin
	endif
endif



export OFILES	:=	$(MAPFILES:.map=.o) $(RAWFILES:.raw=.o) $(PALFILES:.pal=.o) $(BINFILES:.bin=.o) $(PNGFILES:.png=.o) 

$(PCXFILES:.pcx=.o) $(JPEGFILES:.jpg=.o) $(MODFILES:.mod=.o) $(GIFFILES:.gif=.o) $(BMPFILES:.bmp=.o)\
					$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)

export INCLUDE	:=	$(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
					$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
					$(foreach dir,$(LIBDIRS),-I$(dir)/include/nds) \
					-I$(PAPATH)/include/nds\
					-I$(CURDIR)/$(BUILD)

export LIBPATHS	:=	$(foreach dir,$(LIBDIRS),-L$(dir)/lib)

.PHONY: $(BUILD) clean export

#---------------------------------------------------------------------------------
$(BUILD):
	@[ -d $@ ] || mkdir -p $@
	@make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile

#---------------------------------------------------------------------------------
clean:
	@echo clean ...$(TARGET)
	@rm -fr $(BUILD) *.elf *.*ds*

export:
	@echo exporting ...$(TARGET)
	@cp *.nds $(EXPORT_DIR)/$(TARGET).nds

#---------------------------------------------------------------------------------
else

DEPENDS	:=	$(OFILES:.o=.d)

#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
$(OUTPUT).ds.gba	: 	$(OUTPUT).nds

$(OUTPUT).nds	: 	$(OUTPUT).bin

$(OUTPUT).bin	:	$(OUTPUT).elf

$(OUTPUT).elf	:	$(OFILES)

#---------------------------------------------------------------------------------
# Rule to build the soundbank from audio files
#---------------------------------------------------------------------------------
soundbank_bin.bin : $(AUDIOFILES)
#---------------------------------------------------------------------------------
ifneq ($(strip $(DONT_BUILD_MAXMOD_SOUNDBANK)), YES)
	@echo "Generating soundbank..."
	@echo
	@mmutil $^ -d -osoundbank_bin.bin -hsoundbank.h
endif


#---------------------------------------------------------------------------------
%.ds.gba: %.nds
	@echo built ... $(notdir $@)
	@dsbuild $<

ifeq ($(strip $(USE_EFS)), YES)
#	@$(CURDIR)/../efs $(OUTPUT).ds.gba
else
	@cp $(CURDIR)/../$(notdir $@) ../$(notdir $(OUTPUT)).sc.nds
endif
#---------------------------------------------------------------------------------
%.nds: %.bin
ifeq ($(strip $(USE_EFS)), YES)
	@ndstool -c $@ -9 $(TARGET).bin $(ARM7BIN) $(LOGO) $(ICON) "$(TEXT1);$(TEXT2);$(TEXT3)" -d ../nitrofs
#	@$(CURDIR)/../efs $(OUTPUT).nds


else
	@ndstool -c $@ -9 $(TARGET).bin $(ARM7BIN) $(LOGO) $(ICON) "$(TEXT1);$(TEXT2);$(TEXT3)"
endif

#---------------------------------------------------------------------------------
%.bin: %.elf

	@$(OBJCOPY) -O binary $(TARGET).elf $(TARGET).bin

#---------------------------------------------------------------------------------
%.elf:
	@echo $(LD)  $(LDFLAGS) -specs=ds_arm9.specs $(OFILES) $(LIBPATHS) $(LIBS) -o $(TARGET).elf
	@$(LD)  $(LDFLAGS) -specs=ds_arm9.specs $(OFILES) $(LIBPATHS) $(LIBS) -o $(TARGET).elf



#---------------------------------------------------------------------------------
# Compile Targets for C/C++
#---------------------------------------------------------------------------------

#---------------------------------------------------------------------------------
%.o : %.cpp
	@echo $(notdir $<)
	@$(CXX) -MM $(CFLAGS) -o $*.d $<
	@$(CXX) $(CFLAGS) -c $< -o$@

#---------------------------------------------------------------------------------
%.o : %.c
	@echo $(notdir $<)
	@$(CC) -MM $(CFLAGS) -o $*.d $<
	@$(CC)  $(CFLAGS) -c $< -o$@

#---------------------------------------------------------------------------------
%.o : %.s
	@echo $(notdir $<)
	@$(CC) -MM $(CFLAGS) -o $*.d $<
	@$(CC)  $(ASFLAGS) -c $< -o$@

define bin2o
	cp $(<) $(*).tmp
	$(OBJCOPY) -I binary -O elf32-littlearm -B arm \
	--rename-section .data=.rodata \
	--redefine-sym _binary_$*_tmp_start=$*\
	--redefine-sym _binary_$*_tmp_end=$*_end\
	--redefine-sym _binary_$*_tmp_size=$*_size\
	$(*).tmp $(@)
	echo "extern const u8" $(*)"[];" > $(*).h
	echo "extern const u32" $(*)_size[]";" >> $(*).h
	rm $(*).tmp
endef

#---------------------------------------------------------------------------------
%.o	:	%.pcx
#---------------------------------------------------------------------------------
	@echo $(notdir $<)
	@$(bin2o)

#---------------------------------------------------------------------------------
%.o	:	%.bin
#---------------------------------------------------------------------------------
	@echo $(notdir $<)
	@$(bin2o)

#---------------------------------------------------------------------------------
%.o	:	%.png
#---------------------------------------------------------------------------------
	@echo $(notdir $<)
	@$(bin2o)

#---------------------------------------------------------------------------------
%.o	:	%.raw
#---------------------------------------------------------------------------------
	@echo $(notdir $<)
	@$(bin2o)

#---------------------------------------------------------------------------------
%.o	:	%.pal
#---------------------------------------------------------------------------------
	@echo $(notdir $<)
	@$(bin2o)

#---------------------------------------------------------------------------------
%.o	:	%.map
#---------------------------------------------------------------------------------
	@echo $(notdir $<)
	@$(bin2o)

#---------------------------------------------------------------------------------
%.o	:	%.mdl
#---------------------------------------------------------------------------------
	@echo $(notdir $<)
	@$(bin2o)

#---------------------------------------------------------------------------------
%.o	:	%.jpg
#---------------------------------------------------------------------------------
	@echo $(notdir $<)
	@$(bin2o)

#---------------------------------------------------------------------------------
%.o	:	%.mod
#---------------------------------------------------------------------------------
	@echo $(notdir $<)
	@$(bin2o)

#---------------------------------------------------------------------------------
%.o	:	%.gif
#---------------------------------------------------------------------------------
	@echo $(notdir $<)
	@$(bin2o)

#---------------------------------------------------------------------------------
%.o	:	%.bmp
#---------------------------------------------------------------------------------
	@echo $(notdir $<)
	@$(bin2o)


-include $(DEPENDS)

#---------------------------------------------------------------------------------------
endif

lib:
	$(DEVKITPRO)/devkitARM/arm-eabi/bin/ar -cr test.a build/*.o

#---------------------------------------------------------------------------------------


Here is my make output :

Code: Select all

arm-eabi-g++ -g -mthumb-interwork -mno-fpu -L/c/devkitPro/PAlib/lib -lpa9 -specs
=ds_arm9.specs PA_Math.o actions.o cyg-profile.o interface.o item.o main.o misc.
o npc.o objects.o player.o quests.o skillmenu.map.o skillselectmenumap.map.o sou
nd.o top_screen.o ulScreenDisplay.o vfsnitro.o ai.o bgobjects.o collisions.o scr
olling.o Map.o waypoint.o emudetect.o -L/c/devkitPro/libnds/lib -lul -lfilesyste
m -lmm9 -lpng -lz -lfat -lnds9 -o build.elf
interface.o: In function `mainmenu':
interface.c:(.text+0xed0): undefined reference to `ulSetMainLcd'
main.o: In function `CallAllInits':
main.c:(.text+0x96c): undefined reference to `ulSetMainLcd'
misc.o: In function `MySplash':
misc.c:(.text+0x61c): undefined reference to `ulShowSplashScreen'
collect2: ld returned 1 exit status
make[1]: *** [/c/devkitpro/neocompo_profile/neocompo_profile.elf] Error 1
make: *** [build] Error 2
I saw that you don't use the same proc architecture, could you explain what is the difference?
(mine is -mcpu=arm9tdmi -mtune=arm9tdmi )
Thanks

mtheall
Posts: 210
Joined: Thu Feb 03, 2011 10:47 pm

Re: Profiling arm/nds program

Post by mtheall » Sat Aug 18, 2012 11:05 pm

Don't use PAlib. It relies on a severely outdated toolchain and is unsupported.

LeRodeur
Posts: 13
Joined: Tue Jul 31, 2012 2:36 pm

Re: Profiling arm/nds program

Post by LeRodeur » Sat Aug 18, 2012 11:29 pm

I am not using Palib, though this makefile is a modified version of palib. Each part involving Palib has been removed from the makefile
I am using uLibrary of Brunni, I don't really think it's that outdated, it works fine with latest devkitpro and mainly uses opengl functions.
Maybe I should try to recompile the library with the flags you gave me?

WinterMute
Site Admin
Posts: 1862
Joined: Tue Aug 09, 2005 3:21 am
Location: UK
Contact:

Re: Profiling arm/nds program

Post by WinterMute » Fri Aug 24, 2012 10:36 am

Please don't use uLibrary either, it's awful and you won't get support for it here either. You should also get rid of your current Makefile and replace it with a standardised one based on the templates and other provided examples. When you ask questions and show Makefiles like that the experts will be distracted by evidence of poor libraries that have been shown to cause major issues with standard devkitARM installs.

Mtheall, arrrrghhhh! There was a reason I didn't link to that cyg-profile stuff - it can be done better and I'd like to try to get the -pg option working if possible.
Help keep devkitPro toolchains free, Donate today

Personal Blog

LeRodeur
Posts: 13
Joined: Tue Jul 31, 2012 2:36 pm

Re: Profiling arm/nds program

Post by LeRodeur » Fri Aug 24, 2012 1:15 pm

I just changed my makefile this morning in the train, everything seems to compile properly now (I had to make some small changes in ulibrary because a function was implemented as extern in header and caused problem with no -finstrument-functions -mpoke-function-name)
Anyway why is uLibrary that bad? It seems to use mainly opengl functions and I didn't find any deprecated functions.
Hope the link I gave will help you implementing -pg, and sorry for the double post, I refreshed the page because my cellphone didn't print it correctly.
thanks again

mtheall
Posts: 210
Joined: Thu Feb 03, 2011 10:47 pm

Re: Profiling arm/nds program

Post by mtheall » Fri Aug 24, 2012 3:28 pm

WinterMute, I agree it can be done better, but this is what works for me right now. Otherwise I tend to use cpuStartTiming() and friends to get some timing info, which are usually accurate enough for my purposes.

LeRodeur
Posts: 13
Joined: Tue Jul 31, 2012 2:36 pm

Re: Profiling arm/nds program

Post by LeRodeur » Fri Aug 24, 2012 4:11 pm

Anyway, I had some problems with line 96 in your resolve.pl (division by zero)
edit Is it normal that all only the number of calls is correct? all the times are set to 0

Post Reply

Who is online

Users browsing this forum: No registered users and 9 guests