One led per core/thread

All technical discussions and projects around startKIT
dwelch67
Member++
Posts: 22
Joined: Thu Jun 16, 2011 9:01 pm

Re: One led per core/thread

Postby dwelch67 » Mon Dec 30, 2013 12:24 am

I also want to understand the eeu/waiteu instructions, which if they dont apply here can be a separate thread topic.

Thanks,
David
User avatar
segher
XCore Expert
Posts: 843
Joined: Sun Jul 11, 2010 1:31 am

Postby segher » Mon Dec 30, 2013 12:49 am

You cannot use one channel end in multiple threads (at the
same time). With the SETD instruction you say what destination
channel end you want to send data to via this chanend; for
all of your slaves this will be the master chanend.

When you do send data (using OUT) the hardware opens
a virtual circuit to that destination. As long as that circuit
is open, no other circuit to that destination chanend can be
opened, so that all your data arrives neatly in order, not
interleaved with data that others send. When you send an
END control token the circuit is folded up. When you try
to send something but a circuit cannot be opened there is
no error, your thread simply pauses until it can send (actually,
there are some small buffers; you can ignore them most
of the time).
User avatar
Bianco
XCore Expert
Posts: 754
Joined: Thu Dec 10, 2009 6:56 pm

Postby Bianco » Mon Dec 30, 2013 12:50 am

A chanend can receive from multiple senders. If it is important to know from which sender, you will have to implement that in a custom protocol.

Have you by any chance looked at this project?
http://www.xcore.com/projects/31-client ... r-chan-end

Regarding eeu, waiteu:

Code: Select all

setup_resources:
    getr     r0,         XS1_RES_TYPE_TIMER        // (1)
    getr     r1,         XS1_RES_TYPE_CHANEND

    ldap    r11,        tmr_vec                    // (2)
    setv    res[r0],    r11
    ldap    r11,        chan_vec
    setv    res[r1],    r11

    ldc     r2,         1024                      // (3)
    setd    res[r0],    r2
    setc    res[r0],    XS1_SETC_COND_AFTER

    setc    res[r0],    XS1_SETC_IE_MODE_EVENT    // (4)
    setc    res[r1],    XS1_SETC_IE_MODE_EVENT

    eeu     res[r0]                               // (5)
    eeu     res[r1]

    waiteu                                        // (6)

chan_vec:    
    ...        // process event                      (7)

    waiteu                                        // (8)

tmr_vec:
    ...        // process event                      (7)

    waiteu                                        // (8)
At (1) it allocates a timer and a
channel end resource. The resource IDs are saved in the general purpose registers r0
and r1. At (2) it saves the address of the timer event vector (tmr vec) to register r11.
After that it sets the event vector for the resource of which the resource id is saved in
register r0 (timer) to the address saved in register r11. In the same way the event vector
for the channel end is set. At (3) the condition for the timer to generate an event is set
up. It loads the value of 1024 in the data register of the timer. After that it sets that the
timer should generate an event if the timer value is larger than 1024. At (4) it sets that
the two resources should generate events (and not interrupts). This step can be omitted
because events are the default setting. At (5) it enables the generation of events on the
two resources. Even though events can be generated at this stage, event vectors will not
be executed. At (6) it checks if an event has occurred prior to executing this instruction.
If there is no event at the time of the execution of this instruction, the thread will be
blocked until an event occurs. When an event occurs it will execute the event vector of
the resource that generated the event. The event can be directly processed (7) without
saving the context. After processing the event, it can check for pending events or wait
for a new event (8).
User avatar
segher
XCore Expert
Posts: 843
Joined: Sun Jul 11, 2010 1:31 am

Postby segher » Mon Dec 30, 2013 1:21 am

All resources that can generate events (ports, chanends,
and timers) have an enable flag. EEU sets that flag (EDU
clears it; EET and EEF do either, conditionally).

Each thread has an EEBLE flag (the lowest bit in the SR reg)
that you can set with SETSR and clear with CLRSR.

If EEBLE is set, and a resource is ready, and the enable
flag for that resource is set, then an event is taken: the
PC is set to the V reg of that resource, ED is set to the
value in the EV reg of that resource, and EEBLE is cleared.

CLRE clears the enable flags of all resources, and clears EEBLE.
No event can happen anymore without you enabling things
again.

WAITEU enables EEBLE and pauses until an event is taken.

"Ready" for a chanend means there is input data.
dwelch67
Member++
Posts: 22
Joined: Thu Jun 16, 2011 9:01 pm

Postby dwelch67 » Mon Dec 30, 2013 4:59 pm

Thanks, that worked great...for a timer.

Code: Select all

stdcore[0]@0- -A-.----00010000 (_start              +  0) : ldc     r1(0xb), 0xb @5
stdcore[0]@0- -A-.----00010002 (_start              +  2) : get     r0(0x10000), ps[r1(0xb)] @9
stdcore[0]@0- -A-.----00010006 (_start              +  6) : ldc     r2(0x10b), 0x10b @17
stdcore[0]@0- -A-.----0001000a (_start              +  a) : set     ps[r2(0x10b)], r0(0x10000) @25
stdcore[0]@0- -A-.----0001000e (_start              +  e) : ldc     r11(0x6), 0x6 @29
stdcore[0]@0- -A-.----00010010 (_start              + 10) : setc    res[r11(0x6)], 0x8 @33
stdcore[0]@0- -A-.----00010012 (_start              + 12) : setc    res[r11(0x6)], 0xf @37
stdcore[0]@0- -A-.----00010014 (_start              + 14) : ldc     r8(0x2000), 0x2000 @41
stdcore[0]@0- -A-.----00010018 (_start              + 18) : shl     r8(0x200000), r8(0x2000), 0x8 @45
stdcore[0]@0- -A-.----0001001a (_start              + 1a) : setc    res[r8(0x200000)], 0x8 @49
stdcore[0]@0- -A-.----0001001c (_start              + 1c) : ldc     r1(0x6), 0x6 @53
stdcore[0]@0- -A-.----0001001e (_start              + 1e) : setclk  res[r8(0x200000)], r1(0x6) @57
stdcore[0]@0- -A-.----00010022 (setup_resources     +  0) : getr    r0(0x1), 0x1 @61
stdcore[0]@0- -A-.----00010024 (setup_resources     +  2) : getr    r1(0x2), 0x2 @65
stdcore[0]@0- -A-.----00010026 (setup_resources     +  4) : ldap    r11(0x10050), 0x14 @69
stdcore[0]@0- -A-.----00010028 (setup_resources     +  6) : setv    res[r0(0x1)], r11(0x10050) @73
stdcore[0]@0- -A-.----0001002a (setup_resources     +  8) : ldap    r11(0x10040), 0xa @77
stdcore[0]@0- -A-.----0001002c (setup_resources     +  a) : setv    res[r1(0x2)], r11(0x10040) @81
stdcore[0]@0- -A-.----0001002e (setup_resources     +  c) : ldc     r2(0x100), 0x100 @85
stdcore[0]@0- -A-.----00010032 (setup_resources     + 10) : setd    res[r0(0x1)], r2(0x100) @89
stdcore[0]@0- -A-.----00010034 (setup_resources     + 12) : setc    res[r0(0x1)], 0x9 @93
stdcore[0]@0- -A-.----00010036 (setup_resources     + 14) : setc    res[r0(0x1)], 0x2 @97
stdcore[0]@0- -A-.----00010038 (setup_resources     + 16) : setc    res[r1(0x2)], 0x2 @101
stdcore[0]@0- -A-.----0001003a (setup_resources     + 18) : eeu     res[r0(0x1)] @105
stdcore[0]@0- -A-.----0001003c (setup_resources     + 1a) : eeu     res[r1(0x2)] @109
stdcore[0]@0-P-A-.----0001003e (setup_resources     + 1c) : waiteu   @113
stdcore[0]@0Event caused by res 0x00000001, V=0x00010050, EV=0x00000001 @1028
stdcore[0]@0- -A-.----00010050 (tmr_vec             +  0) : ldc     r10(0xabcd), 0xabcd @1036
stdcore[0]@0- -A-.----00010054 (tmr_vec             +  4) : out     res[r8(0x200000)], r10(0xabcd) @1040
stdcore[0]@0- -A-.----00010056 (tmr_vec             +  6) : ldap    r11(0x10050), -0x4 @1044
stdcore[0]@0- -A-.----00010058 (tmr_vec             +  8) : setv    res[r0(0x1)], r11(0x10050) @1048
stdcore[0]@0- -A-.----0001005a (tmr_vec             +  a) : ldap    r11(0x10040), -0xe @1052
stdcore[0]@0- -A-.----0001005c (tmr_vec             +  c) : setv    res[r1(0x2)], r11(0x10040) @1056
stdcore[0]@0-P-A-.----0001005e (tmr_vec             +  e) : waiteu   @1060
stdcore[0]@0Event caused by res 0x00000001, V=0x00010050, EV=0x00000001 @1064
stdcore[0]@0- -A-.----00010050 (tmr_vec             +  0) : ldc     r10(0xabcd), 0xabcd @1072
stdcore[0]@0- -A-.----00010054 (tmr_vec             +  4) : out     res[r8(0x200000)], r10(0xabcd) @1076
stdcore[0]@0- -A-.----00010056 (tmr_vec             +  6) : ldap    r11(0x10050), -0x4 @1080
stdcore[0]@0- -A-.----00010058 (tmr_vec             +  8) : setv    res[r0(0x1)], r11(0x10050) @1084
stdcore[0]@0- -A-.----0001005a (tmr_vec             +  a) : ldap    r11(0x10040), -0xe @1088
stdcore[0]@0- -A-.----0001005c (tmr_vec             +  c) : setv    res[r1(0x2)], r11(0x10040) @1092
stdcore[0]@0-P-A-.----0001005e (tmr_vec             +  e) : waiteu   @1096
stdcore[0]@0Event caused by res 0x00000001, V=0x00010050, EV=0x00000001 @1100
stdcore[0]@0- -A-.----00010050 (tmr_vec             +  0) : ldc     r10(0xabcd), 0xabcd @1108
stdcore[0]@0- -A-.----00010054 (tmr_vec             +  4) : out     res[r8(0x200000)], r10(0xabcd) @1112
It also appears I have been fighting the tools as well, yet another research project. if you replace r0 and r1 with r2 and r3 above for example (setup resources on down) it stops working. If I change the way and what .xn file I specify on the command line, if I basically specify the STARTKIT.xn file then it adds a pile of code in front of my _start and perhaps that makes it all work in the sim (with r2 and r3 instead of r0 and r1).

David
dwelch67
Member++
Posts: 22
Joined: Thu Jun 16, 2011 9:01 pm

Postby dwelch67 » Mon Dec 30, 2013 7:43 pm

so this app

Code: Select all

_start:
    ldc r1,0x00B
    get r0,ps[r1]       # get ram base
    ldc r2,0x10B
    set ps[r2],r0       # set vector base (to match ram base)

    ldc  r11, 0x6       # the I/O ports need a clock
    setc res[r11], 0x8  # setci
    setc res[r11], 0xf  # setci

    # define XS1_PORT_32A 0x200000
    ldc r8,0x2000
    shl r8,r8,8
    setc res[r8],0x8    # turn the port on
    ldc r1,0x6          # give it a clock
    setclk res[r8],r1


setup_resources:
    getr r2,1           # XS1_RES_TYPE_TIMER

    ldap r11,tmr_vec
    setv res[r2],r11

    ldc r10,256
    setd res[r2],r10
    setc res[r2],0x9    # XS1_SETC_COND_AFTER

    setc res[r2],0x2    # XS1_SETC_IE_MODE_EVENT

    eeu res[r2]

    waiteu

tmr_vec:
    ldc r10,0xABCD
    out res[r8],r10
    freer res[r2]
    clre
    waiteu
built with these commands

Code: Select all

	xas thread_hand4.s -o thread_hand4.o
	xcc -O2 thread_hand4.o -target=STARTKIT -o thread_hand4.xe -nostartfiles -nostdlib -nodefaultlibs 
	#xmap.orig -target=STARTKIT --defsymbol _default_clkblk=0x6 -march=xs1b -o thread_hand4.xe --first thread_hand4.o 
	xobjdump -D thread_hand4.xe > thread_hand4.list
creates a binary with two loadable modules, both start with _start at address 0x10000.

Code: Select all

Loadable 1 for tile[0] (node "0", tile 0):

Disassembly of section .text (size: 240)

<_start>:
             0x00010000: 00 68:       ldc (ru6)       r0, 0x0
             0x00010002: 40 68:       ldc (ru6)       r1, 0x0
             0x00010004: 80 68:       ldc (ru6)       r2, 0x0
             0x00010006: c0 68:       ldc (ru6)       r3, 0x0
             0x00010008: 00 69:       ldc (ru6)       r4, 0x0
 
...


Loadable 2 for tile[0] (node "0", tile 0):

Disassembly of section .text (size: 66)

<_start>:
             0x00010000: 4b 68:       ldc (ru6)       r1, 0xb
             0x00010002: d1 fe ec 17: get (l2r)       r0, ps[r1]
             0x00010006: 04 f0 8b 68: ldc (lru6)      r2, 0x10b
             0x0001000a: c2 fe ec 1f: set (lr2r)      ps[r2], r0
Built differently, using different targets, you can get it to build only the code that I gave it not some other code. In that case it runs fine if I use r0 for the resource but not if r2.

How in a real chip and not the simulator can you have these two programs load at the same place in the same tile?

For example use this .xn file derived from STARTKIT.xn

Code: Select all

<?xml version="1.0" encoding="UTF-8"?>
<Network xmlns="http://www.xmos.com"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.xmos.com http://www.xmos.com">
  <Type>Board</Type>
  <Name>blink_led example config</Name>

  <Declarations>
    <Declaration>tileref tile[1]</Declaration>
  </Declarations>

  <Packages>
    <Package id="0" Type="XS1-L1A-TQ128">
      <Nodes>
        <Node Id="0" InPackageId="0" Type="XS1-L8A-64" Oscillator="24MHz" SystemFrequency="500MHz">
          <Tile Number="0" Reference="tile[0]"/>
        </Node>
      </Nodes>
    </Package>
  </Packages>

  <JTAGChain>
     <JTAGDevice NodeId="0"/>
  </JTAGChain>

</Network>
And this to build

Code: Select all

	xas thread_hand4.s -o thread_hand4.o
	xmap -targetfile=hello.xn --defsymbol _default_clkblk=0x6 -march=xs1b -o thread_hand4.xe --first thread_hand4.o 
	xobjdump -D thread_hand4.xe > thread_hand4.list
It then only generates one loadable image and that image only works

Code: Select all

xsim -t --max-cycles 4000 thread_hand4.xe 
if you use r0 not r2 to hold the resource.

adding a mov r0,r2 after the resource has been allocated you can use r2 to do everything, but the program now works, so there is some magic to having that value (0x01) in r0 to make this work.

Thanks,
David
dwelch67
Member++
Posts: 22
Joined: Thu Jun 16, 2011 9:01 pm

Postby dwelch67 » Mon Dec 30, 2013 8:40 pm

It looks like I am falling into an OS system call (_DoSysCall?) depending on the value of r0 depends on the success or failure on the simulator. Is this a simulator thing or a chip/hardware thing? Why does it happen at/after the event and not immediately when waiteu is invoked? It appears to be encoding a waiteu not a dcall which is only one bit different according to the docs. Is there yet another register/bit somewhere that needs to be set or unset in order to not make a system call?
User avatar
segher
XCore Expert
Posts: 843
Joined: Sun Jul 11, 2010 1:31 am

Postby segher » Mon Dec 30, 2013 9:47 pm

The first loadable is used by the debugger to set up the
PLL configuration, etc.; the second loadable is your program.

Your program didn't take a debug interrupt (DCALL) nor
a system call (KCALL); it looks like it took a boring exception
instead. And you didn't initialise the KEP register, so it
jumped who-knows-where. From there, things can only
go downhill.

To figure out where things went wrong, do set up KEP
properly. If I had to guess I'd say that FREER looks bad,
but just try and see :-)
dwelch67
Member++
Posts: 22
Joined: Thu Jun 16, 2011 9:01 pm

Postby dwelch67 » Tue Dec 31, 2013 1:15 am

I tried setting kep before without success, will try it again, thanks,
David
User avatar
segher
XCore Expert
Posts: 843
Joined: Sun Jul 11, 2010 1:31 am

Postby segher » Tue Dec 31, 2013 1:28 am

Make sure the value you put in KEP is properly aligned;
maybe that bit you?

Who is online

Users browsing this forum: No registered users and 1 guest