Date:2011-10-10 03:19:28 (7 years 8 months ago)
Author:Werner Almesberger
Commit:9e32d56ce93d106e17690115b2624e5c4fc20a1b
Message:m1/perf/sched.c: synchronize with upstream version

Files: m1/perf/sched.c (24 diffs)

Change Details

m1/perf/sched.c
11/*
2 * sched.c - O(n) ... O(n^2) scheduler
2 * lnfpus.c - O(n) ... O(n^2) scheduler
33 *
4 * Written 2011 by Werner Almesberger
4 * Copyright (C) 2011 Werner Almesberger
55 *
66 * Based on gfpus.c
77 * Copyright (C) 2007, 2008, 2009, 2010 Sebastien Bourdeauducq
...... 
123123    } fconv;
124124
125125    for(i = 0; i < fragment->nbindings; i++)
126               if (fragment->bindings[i].isvar)
126        if(fragment->bindings[i].isvar)
127127            registers[i] = 0;
128128        else {
129129            fconv.f = fragment->bindings[i].b.c;
...... 
176176    struct list *first;
177177
178178    first = list->next;
179    if (first == list)
179    if(first == list)
180180        return NULL;
181181    list_del(first);
182182    return first;
...... 
203203
204204static void list_concat(struct list *a, struct list *b)
205205{
206    if (b->next != b) {
206    if(b->next != b) {
207207        a->prev->next = b->next;
208208        b->next->prev = a->prev;
209209        b->prev->next = a;
...... 
218218 */
219219
220220#define foreach(var, head) \
221    for (var = (void *) ((head))->next; \
221    for(var = (void *) ((head))->next; \
222222        (var) != (void *) (head); \
223223        var = (void *) ((struct list *) (var))->next)
224224
...... 
238238    int vm_reg, pfpu_reg, vm_idx;
239239
240240    vm_reg = setter->vm_insn->dest;
241    if (vm_reg >= 0) {
241    if(vm_reg >= 0) {
242242        pfpu_reg = vm_reg;
243243        sc->pfpu_regs[vm_reg].vm_reg = vm_reg; /* @@@ global init */
244244    } else {
245245        reg = list_pop(&sc->unallocated);
246        if (!reg)
246        if(!reg)
247247            return -1;
248248
249249        #ifdef REG_STATS
250250        sc->curr_regs++;
251        if (sc->curr_regs > sc->max_regs)
251        if(sc->curr_regs > sc->max_regs)
252252            sc->max_regs = sc->curr_regs;
253253        #endif
254254
...... 
272272    int vm_idx;
273273    struct vm_reg *reg;
274274
275    if (vm_reg >= 0)
275    if(vm_reg >= 0)
276276        return;
277277
278278    vm_idx = vm_reg2idx(vm_reg);
279279    reg = sc->regs+vm_idx;
280280
281281    assert(reg->refs);
282    if (--reg->refs)
282    if(--reg->refs)
283283        return;
284284
285285    Dprintf(" free reg %d\n", reg->pfpu_reg);
...... 
309309
310310static void mark(int vm_reg)
311311{
312    if (vm_reg > 0)
312    if(vm_reg > 0)
313313        sc->pfpu_regs[vm_reg].used = 1;
314314}
315315
...... 
319319{
320320    int i;
321321
322    sc->regs =
323        calloc(frag->nbindings-frag->next_sur, sizeof(struct vm_reg));
324    if (!sc->regs)
325        return -1;
326
327322    get_registers(frag, registers);
328323
329    for (i = 0; i != frag->ninstructions; i++) {
324    for(i = 0; i != frag->ninstructions; i++) {
330325        mark(frag->code[i].opa);
331326        mark(frag->code[i].opb);
332327        mark(frag->code[i].dest);
333328    }
334329
335330    list_init(&sc->unallocated);
336    for (i = PFPU_SPREG_COUNT; i != PFPU_REG_COUNT; i++)
337        if (!sc->pfpu_regs[i].used)
331    for(i = PFPU_SPREG_COUNT; i != PFPU_REG_COUNT; i++)
332        if(!sc->pfpu_regs[i].used)
338333            list_add_tail(&sc->unallocated, &sc->pfpu_regs[i].more);
339334
340335    return 0;
...... 
352347    reg = sc->regs+vm_reg2idx(reg_num);
353348    ref->insn = insn;
354349    ref->dep = reg->setter;
355    if (insn->vm_insn->dest == reg_num)
350    if(insn->vm_insn->dest == reg_num)
356351        insn->rmw = 1;
357    if (!ref->dep)
352    if(!ref->dep)
358353        reg->refs++;
359354    else {
360355        list_add_tail(&ref->dep->dependants, &ref->more);
...... 
378373
379374    list_init(&sc->unscheduled);
380375    list_init(&sc->waiting);
381    for (i = 0; i != PFPU_PROGSIZE; i++)
376    for(i = 0; i != PFPU_PROGSIZE; i++)
382377        list_init(sc->ready+i);
383378
384    for (i = 0; i != frag->ninstructions; i++) {
379    for(i = 0; i != frag->ninstructions; i++) {
385380        insn = sc->insns+i;
386381        insn->vm_insn = frag->code+i;
387382        insn->arity = fpvm_get_arity(frag->code[i].opcode);
388383        insn->latency = pfpu_get_latency(frag->code[i].opcode);
389384        list_init(&insn->dependants);
390385        switch (insn->arity) {
391        case 3:
392            add_data_ref(insn, &insn->cond, FPVM_REG_IFB);
393            /* fall through */
394        case 2:
395            add_data_ref(insn, &insn->opb, frag->code[i].opb);
396            /* fall through */
397        case 1:
398            add_data_ref(insn, &insn->opa, frag->code[i].opa);
399            /* fall through */
400        case 0:
401            reg = sc->regs+vm_reg2idx(frag->code[i].dest);
402            if (reg->setter) {
403                reg->setter->next_setter = insn;
404                foreach (ref, &reg->setter->dependants)
405                    if (ref->insn != insn)
386            case 3:
387                add_data_ref(insn, &insn->cond, FPVM_REG_IFB);
388                /* fall through */
389            case 2:
390                add_data_ref(insn, &insn->opb, frag->code[i].opb);
391                /* fall through */
392            case 1:
393                add_data_ref(insn, &insn->opa, frag->code[i].opa);
394                /* fall through */
395            case 0:
396                reg = sc->regs+vm_reg2idx(frag->code[i].dest);
397                if(reg->setter) {
398                    reg->setter->next_setter = insn;
399                    foreach(ref, &reg->setter->dependants)
400                        if(ref->insn != insn)
401                            insn->unresolved++;
402                    if(!insn->rmw)
406403                        insn->unresolved++;
407                if (!insn->rmw)
408                    insn->unresolved++;
409            } else {
410                if (!insn->rmw)
411                    insn->unresolved += reg->refs;
412                reg->first_setter = insn;
413            }
414            reg->setter = insn;
415            break;
416        default:
417            abort();
404                } else {
405                    if(!insn->rmw)
406                        insn->unresolved += reg->refs;
407                    reg->first_setter = insn;
408                }
409                reg->setter = insn;
410                break;
411            default:
412                abort();
418413        }
419        if (insn->unresolved)
414        if(insn->unresolved)
420415            list_add_tail(&sc->unscheduled, &insn->more);
421416        else
422417            list_add_tail(&sc->ready[0], &insn->more);
...... 
425420#ifdef LCPF
426421    struct data_ref *dep;
427422
428    for (i = frag->ninstructions-1; i >= 0; i--) {
423    for(i = frag->ninstructions-1; i >= 0; i--) {
429424        insn = sc->insns+i;
430425#if 0
431426        /*
...... 
435430         * This is a degenerate case that's probably not worth
436431         * spending much effort on.
437432         */
438        if (insn->next_setter) {
433        if(insn->next_setter) {
439434            insn->distance =
440435                insn->next_setter->distance-insn->distance+1;
441            if (insn->distance < 1)
436            if(insn->distance < 1)
442437                insn->distance = 1;
443438        }
444439#endif
445        foreach (dep, &insn->dependants)
446            if (dep->insn->distance > insn->distance)
440        foreach(dep, &insn->dependants)
441            if(dep->insn->distance > insn->distance)
447442                insn->distance = dep->insn->distance;
448443        /*
449444         * While it would be more correct to add one for the cycle
...... 
463458    int slot;
464459
465460    assert(insn->unresolved);
466    if (--insn->unresolved)
461    if(--insn->unresolved)
467462        return;
468463    Dprintf(" unblocked %lu -> %u\n", insn-sc->insns, insn->earliest);
469464    list_del(&insn->more);
470465    slot = insn->earliest;
471    if (slot <= sc->cycle)
466    if(slot <= sc->cycle)
472467        slot = sc->cycle+1;
473468    list_add_tail(sc->ready+slot, &insn->more);
474469}
...... 
479474    struct insn *setter = ref->dep;
480475    struct vm_reg *reg;
481476
482    if (setter) {
477    if(setter) {
483478        put_reg(setter->vm_insn->dest);
484        if (setter->next_setter && setter->next_setter != ref->insn)
479        if(setter->next_setter && setter->next_setter != ref->insn)
485480            unblock(setter->next_setter);
486481    } else {
487482        reg = sc->regs+vm_reg2idx(vm_reg);
488        if (reg->first_setter && !reg->first_setter->rmw)
483        if(reg->first_setter && !reg->first_setter->rmw)
489484            unblock(reg->first_setter);
490485    }
491486}
...... 
493488
494489static void unblock_after(struct insn *insn, int cycle)
495490{
496    if (insn->earliest <= cycle)
491    if(insn->earliest <= cycle)
497492        insn->earliest = cycle+1;
498493    unblock(insn);
499494}
...... 
511506        insn->vm_insn->opb);
512507
513508    switch (insn->arity) {
514    case 3:
515        put_reg_by_ref(&insn->cond, FPVM_REG_IFB);
516        /* fall through */
517    case 2:
518        CODE(sc->cycle).opb = lookup_pfpu_reg(insn->vm_insn->opb);
519        put_reg_by_ref(&insn->opb, insn->vm_insn->opb);
520        /* fall through */
521    case 1:
522        CODE(sc->cycle).opa = lookup_pfpu_reg(insn->vm_insn->opa);
523        put_reg_by_ref(&insn->opa, insn->vm_insn->opa);
524        break;
525    case 0:
526        break;
527    default:
528        abort();
509        case 3:
510            put_reg_by_ref(&insn->cond, FPVM_REG_IFB);
511            /* fall through */
512        case 2:
513            CODE(sc->cycle).opb = lookup_pfpu_reg(insn->vm_insn->opb);
514            put_reg_by_ref(&insn->opb, insn->vm_insn->opb);
515            /* fall through */
516        case 1:
517            CODE(sc->cycle).opa = lookup_pfpu_reg(insn->vm_insn->opa);
518            put_reg_by_ref(&insn->opa, insn->vm_insn->opa);
519            break;
520        case 0:
521            break;
522        default:
523            abort();
529524    }
530525
531526    reg = alloc_reg(insn);
532    if (reg < 0)
527    if(reg < 0)
533528        return -1;
534529    CODE(end).dest = reg;
535530    CODE(sc->cycle).opcode = fpvm_to_pfpu(insn->vm_insn->opcode);
536531
537    foreach (ref, &insn->dependants)
532    foreach(ref, &insn->dependants)
538533        unblock_after(ref->insn, end);
539    if (insn->next_setter && !insn->next_setter->rmw)
534    if(insn->next_setter && !insn->next_setter->rmw)
540535        unblock_after(insn->next_setter,
541536            end-insn->next_setter->latency);
542537
...... 
550545    int n = 0;
551546    const struct list *p;
552547
553    for (p = list->next; p != list; p = p->next)
548    for(p = list->next; p != list; p = p->next)
554549        n++;
555550    return n;
556551}
...... 
565560    struct insn *best;
566561
567562    remaining = sc->frag->ninstructions;
568    for (i = 0; remaining; i++) {
569        if (i == PFPU_PROGSIZE)
563    for(i = 0; remaining; i++) {
564        if(i == PFPU_PROGSIZE)
570565            return -1;
571566
572567        sc->cycle = i;
...... 
575570
576571        list_concat(&sc->waiting, sc->ready+i);
577572        best = NULL;
578        foreach (insn, &sc->waiting) {
573        foreach(insn, &sc->waiting) {
579574            end = i+insn->latency;
580            if (end >= PFPU_PROGSIZE)
575            if(end >= PFPU_PROGSIZE)
581576                return -1;
582            if (!CODE(end).dest) {
577            if(!CODE(end).dest) {
583578#ifdef LCPF
584                if (!best || best->distance < insn->distance)
579                if(!best || best->distance < insn->distance)
585580                    best = insn;
586581#else
587582                best = insn;
...... 
589584#endif
590585            }
591586        }
592        if (best) {
593            if (issue(best, code) < 0)
587        if(best) {
588            if(issue(best, code) < 0)
594589                return -1;
595590            list_del(&best->more);
596591            remaining--;
597592        }
598        if (CODE(i).dest)
593        if(CODE(i).dest)
599594            put_reg(sc->pfpu_regs[CODE(i).dest].vm_reg);
600595    }
601596
...... 
604599     */
605600    last = i;
606601    end = i+MAX_LATENCY;
607    if (end > PFPU_PROGSIZE)
602    if(end > PFPU_PROGSIZE)
608603        end = PFPU_PROGSIZE;
609    while (i != end) {
610        if (CODE(i).dest)
604    while(i != end) {
605        if(CODE(i).dest)
611606            last = i+1;
612607        i++;
613608    }
...... 
615610}
616611
617612
618static int init_scheduler_context(struct fpvm_fragment *frag,
613int gfpus_schedule(struct fpvm_fragment *frag, unsigned int *code,
619614    unsigned int *reg)
620615{
621    sc = calloc(1, sizeof(*sc));
622    if (!sc)
623        return -1;
616    /*
617     * allocate context and registers on stack because standalone FN has no
618     * memory allocator
619     */
620    struct sched_ctx sc_alloc;
621    struct vm_reg regs[frag->nbindings-frag->next_sur];
622    pfpu_instruction vecout;
623    int res;
624624
625printf("greetings %lu %lu\n", sizeof(*sc), sizeof(regs));
626    sc = &sc_alloc;
627    memset(sc, 0, sizeof(*sc));
625628    sc->frag = frag;
629    sc->regs = regs;
630    memset(regs, 0, sizeof(regs));
626631
627    if (init_registers(frag, reg) < 0) {
628        free(sc);
632    if(init_registers(frag, reg) < 0)
629633        return -1;
630    }
631
632634    init_scheduler(frag);
633    return 0;
634}
635
636
637int gfpus_schedule(struct fpvm_fragment *frag, unsigned int *code,
638    unsigned int *reg)
639{
640    pfpu_instruction vecout;
641    int res;
642635
643    if (init_scheduler_context(frag, reg) < 0)
644        return -1;
645636    memset(code, 0, PFPU_PROGSIZE*sizeof(*code));
646637    res = schedule(code);
647638
...... 
649640    printf("regs: %d/%d\n", sc->curr_regs, sc->max_regs);
650641#endif
651642
652    free(sc->regs);
653    free(sc);
654    if (res < 0)
643    if(res < 0)
655644        return res;
656    if (frag->vector_mode)
645    if(frag->vector_mode)
657646        return res;
658    if (res == PFPU_PROGSIZE)
647    if(res == PFPU_PROGSIZE)
659648        return -1;
660649
661650    vecout.w = 0;

Archive Download the corresponding diff file

Branches:
master



interactive