Shop OBEX P1 Docs P2 Docs Learn Events
Examples of playing with COGINITs (P2-10-10-15 image) — Parallax Forums

Examples of playing with COGINITs (P2-10-10-15 image)

This is an example of everything I've been able to think of doing with COGINIT so far. The program is targeted for the 1-2-3 board but it only uses 8 cogs at most and keeps LEDs to less than 16, so I think it works on DE2 (I can test/verify at a later date). I've tried to filter out my dumb mistakes and misunderstandings. What I see as problems/concerns/gotchas are legitimate (I believe anyway).

Here's the code if you don't want to download and print to follow this:
dat
	orgh	0
	
	loc	        ptra,#@jmp_hblink	' set COG3 DEBUG vector prior to
	rdlong	vector,ptra		' COGINIT
	wrlong	vector,##DEBUGV_3
cog1	
	loc	        adra, #@blink
	coginit	#1, adra	' boring old COGINIT - COGINIT does load
			        	' of COGRAM starting at blink for $1F0 longs
cog2
	loc	        adra, #@cogwait
	coginit	#2, adra	' another COGINIT - just to see that you can
				        ' gather COG images under multiple 'org 0'
				       ' this one will COGINIT inside itself
cog3	
	loc	        adra, #@blink
	coginit	#3, adra	' COGINIT IRET vector is set to jmp #@hblink
cog4
	coginit	#$24,#@cog_prestart ' start COG in HUBEXEC, load it yourself
				    ' jump to COGEXEC after load and any init
cog5
	loc	        adra,#@cogwait
	coginit	#$25, adra	' like start of COG2 above but starts in 
				' HUBEXEC - this was acting differntly 
				' before I moved the COG image orgs after 
				' 'org $1000 - needs more investigation
cog6
	loc	       adra,#@cogwait
	coginit    #6, adra		' this COG gets it's DEBUG vector changed
				' by the COG0 HUBEXEC code after COGINIT
cog7
	loc	        adra, #@blink
	coginit	#7, adra	' run a high cog to get different blink rate
	
	mov	        delay,#1
	shl	        delay,#28
	waitx	delay		' let COG6 wait a bit before we reset
	loc	        ptra,#@jmp_hblink	' DEBUG vector and then re-COGINIT it
	rdlong	vector,ptra	
	wrlong	vector,##DEBUGV_6
	loc	        adra,#@blink
	coginit	#6, adra	' force a stalled COG to go to "debug"
	' kill COG0
	cogid	me
	cogstop	me

' HUBEXEC code to load a COG's COGRAM with code before jumping to it.
cog_prestart
	mov	        delay,#1
	shl	        delay,#26
	waitx	delay
	loc	        ptra,#@cogwait	' grab the HUBRAM address of the image 
				' you built for this COG
	setq	        #$1F8		' could load just the actual size
	rdlong	0,ptra

	' at this point, you could do any intialiazation of COGRAM 
	' required while still in HUBEXEC mode - this allows you
	' to remove intialiation code from precious COG space if needed

	jmp	         #0		' this could be any COGRAM entry point
				' you choose - it depends on how you build
				' your COG image under the org

' some HUBRAM variable space
' This gets interesting and probabaly needs some experimenting 
' and some examples and use cases documented
' 
me		        long	0
delay		long	50_000_000
vector		long	0

		org	0
' Build a COG image here 
cogwait		
		cogid	me2
		setb	        dirb,me2
		setb	        outb,me2
		shl	        ticks, me2
		waitx	ticks
		notb	        outb,me2
		loc	        adra,#@blink
		coginit	me2,adra	' restart myself with a new COG image

ticks		long	50_000_000	' this value gets loaded into COGRAM
					' so the value is only initialized when
					' you start this code in COGEXEC
					' for HUBEXEC, this variable 
					' needs to be intialized as long as it
					' is defined before $1F0 - if you move
					' COG org 0 AFTER "orgh $1000" it does 
					' not need to be intialized - puzzling

me2		res	1		' needed to call this me2 since labels 
					' are global - local labels only have
					' scope between global labels


' Build *MORE* of my HUB image here
		orgh	$1000
jmp_hblink	jmp	#@hblink ' insruction to load DEBUG vector with		

' this is code that will run as HUBEXEC - my "debug" routine
hblink
		cogid	me
		add	        me,#8
		mov	        delay,#1	' you actually need to initialize
		shl	        delay,#23	' delay since it really exists in
					' COGRAM when you refer to it in 
					' an S or D field - the initialized
					' value is in HUBRAM if you want it 
		setb	        dirb,me	
hblink1		
		notb	        outb,me
		waitx	delay
		jmp	        @hblink1

'*****************************
'***** COG IMAGE FOLLOWS *****	
'*****************************
		org	0
' build a COG image here
blink
		cogid	x
		setb	        dirb,x
		notb	        outb,x
		add	        x,#16
		shl	        x,#18
		waitx	x
		jmp	       @blink
x		long	       0
		


con
' addresses for debug Interrupt vectors

DEBUGV_0	=	$FFFC0		' COG0
DEBUGV_1	=	$FFFC4		' COG1
DEBUGV_2	=	$FFFC8		' COG2
DEBUGV_3	=	$FFFCC		' COG3
DEBUGV_4	=	$FFFD0		' COG4
DEBUGV_5	=	$FFFD4		' COG5
DEBUGV_6	=	$FFFD8		' COG6
DEBUGV_7	=	$FFFDC		' COG7
DEBUGV_8	=	$FFFE0		' COG8
DEBUGV_9	=	$FFFE4		' COG9
DEBUGV_A	=	$FFFE8		' COGA
DEBUGV_B	=	$FFFEC		' COGB
DEBUGV_C	=	$FFFF0		' COGC
DEBUGV_D	=	$FFFF4		' COGD
DEBUGV_E	=	$FFFE8		' COGE
DEBUGV_F	=	$FFFEC		' COGF

General notes:
1) I was able to use "COGINIT #cog,#@target" UNTIL I moved the COGRAM sections (org 0) past the "orgh $1000", once I did this, I needed to use LOC and COGINIT as in the code above. When moved higher in hubram, you get the "exceeds 511" message. I understand this and understand why you need the LOC & COGINIT. It isn't a problem since usually your target will be in a higher address range - just use LOC & COGINIT all the time :)

2) There are also some variable initialization issues when running in HUBEXEC - I think I understand them but want to investigate further.

3) I think the definition of variables in HUBRAM and how they are used is going to take some documenting. More will follow on this as I play more.

4) Global labels. You'll notice that I have a "me" and a "Me2" because the labels are global to the program. Current local labels ":me" only have scope between global labels. Some sort of "section local" label would be nice.

This program:

It basically just tries to show all the varios ways you can use COGINIT to fire off new COGs with COGINIT loading COGs and running in COGEXEC, the COG starting in HUBEXEC and loading itself, the DEBUG vectors and such. Hopefully the examples will get anyone going if they are stuck or trigger some inspiration on things I didn't try. The cog0-cog7 labels aren't used in the program but help the narrative. All the COGINITs are using named COGS instead of "next available" just so we have control.

The program starts in HUBEXEC at HUBRAM $0 running in COG0. The first thing it does is replace the IRET0 in the debug vectors for COG3 so it points to a debug routine, we'll use this later.

Once COG0 is done with all the steps below, it kills itself

COG1: just a standard COGINIT of COG1. The COGINIT loads $1F0 (or $1F8) longs from HUBRAM starting at the target address. COG1 starts running at the target address. Nothing unexpected here. This COG image happens to be above the $1000 HUBRAM address.

COG2: Another standard COGINIT of COG2. The COG image in this case is below the $1000 HUBRAM address - in this case, it is under the $1FF HUBRAM space and would actually work as "COGINIT $2,#@cogwait" without the LOC.

COG3: COGINIT of COG3 - the DEBUG vector has been reset to point to my debug routine hblink instead of being the default IRET0. This debug ends up running in HUBEXEC even though you did not specify HUBEXEC on the COGINIT. Not unexpected base on addresses involved. I believe you need to pay attention to D and S registers here - your debug code will see the COGRAM of the running COG for any D and S references. This isn't a surprise either but does cause concerns with anything you expect to be initialized because you initialized it in your programs variable space.

COG4: COGINIT to some HUBEXEC code to load and initialize COGRAM. When done, you just JMP to the entry point of your COG code. This is kind of cool in that you can have all your initialization code in HUBRAM and not use any precious COGRAM for initialization code. I didn't find any surprises or unexpected side effects here. The obvious follow on here is to recover the HUBRAM space this image sat in for buffer space or another COG image. This ability to start in HUBEXEC, load your own COGRAM and then switch to COGEXEC has a lot of potential. Cool beans!! :)

COG5: The same thing we did with COG2 except we set the HUBEXEC bit. This has different results depending on where your COG image is defined. If it is below $1FF, then any variables you have defined do NOT have the defined values. In this example, the COG does NOT wait with the LED on like the same code does with COG2, it goes directly to the COGINIT of the blink routine. This code appears to be location dependent and something you need to be aware of. Pre-initialized variables in HUBEXEC mode have not given me consistent results depending on where they end up in the memory space. I'm still not sure I can predict the outcome until I try it.

COG6: This start out like the COG2 example except in a few lines, the COG0 HUBEXEC code goes out to change the debug vector. Kind of cool to effect other COGs from code running in another COG. Bunches of potential in this feature as well as now having interrupts. :)

COG7: nothing exciting, just another blinking COG. I was using it during testing to make sure I didn't break things.

I think that is everything of note in this program. There is a lot more COGINIT stuff to play with, I'm sure. If I missed something, let me know. If you dispute anything or want to correct any of my bad assumptions or conclusions, PLEASE let em know. If I need to clarify things, well, just ask.

If you have something you want me to try and are too lazy/busy or don't have a FPGA yet, let me know.
Sign In or Register to comment.