Date:2011-09-18 05:51:17 (7 years 9 months ago)
Author:Werner Almesberger
Commit:64e2a3c6b7841ab2b63fa265219a1e497e8242b2
Message:m1/perf/: scheduler cleanup; output comparison tool

Files: m1/perf/Makefile (3 diffs)
m1/perf/eval.pl (1 diff)
m1/perf/sched.c (15 diffs)

Change Details

m1/perf/Makefile
33M1SWINC_DIR=$(M1)/milkymist/software/include
44M1SWLIB_DIR=$(M1)/milkymist/software/libfpvm
55
6CFLAGS_COMMON=-Wall -g -pg # -DCOMP_DEBUG
6#CFLAGS_EXTRA=-DCOMP_DEBUG
7CFLAGS_EXTRA=
8CFLAGS_COMMON=-Wall -g -pg $(CFLAGS_EXTRA)
79CFLAGS=$(CFLAGS_COMMON) \
810       -I$(COMPILER_DIR) \
911       -Ifakes -I$(M1SWINC_DIR)
...... 
1517LIBFPVM_A = $(M1SWLIB_DIR)/libfpvm.a
1618OBJS = main.o $(COMPILER_O)
1719
20.PHONY: all clean path
21
1822all: main
1923
2024main: $(OBJS) $(LIBFPVM_A)
...... 
3337        $(MAKE) -C $(M1SWLIB_DIR) clean
3438        $(MAKE) -C $(COMPILER_DIR) clean
3539        rm -f $(OBJS)
40
41path:
42        @echo $(M1)
m1/perf/eval.pl
1#!/usr/bin/perl
2
3#while (<>) {
4# last if /per-vertex PFPU fragment/;
5#}
6
7$i = 0;
8while (<>) {
9    next unless
10        /^(\d+):\s+(\S+)\s+(R\d+)?(,(R\d+))?.*?(->\s+(R\d+))?\s*$/;
11    # 1 2 3 4 5 6 7
12    ($c, $op, $a, $b, $d) = ($1, $2, $3, $5, $7);
13    undef $e;
14    $e = $1 if /E=(\d+)>/;
15    die if $c != $i;
16
17    $a = $reg{$a} if defined $reg{$a};
18    $b = $reg{$b} if defined $reg{$b};
19
20    if ($op eq "IF") {
21        $expr = "(IF $reg{002} $a $b)";
22    } elsif ($op eq "VECTOUT") {
23        $res = "$a\n$b\n";
24    } elsif (defined $b) {
25        $expr = "($op $a $b)";
26    } elsif (defined $a) {
27        $expr = "($op $a)";
28    } else {
29        $expr = "($op)";
30    }
31
32    $val[$e] = $expr if defined $e;
33    $reg{$d} = $val[$i] if defined $d;
34    $i++;
35}
36
37print $res;
m1/perf/sched.c
3131#include <hw/pfpu.h>
3232
3333
34#define MAX_LATENCY 8 /* maximum latency; okay to make this bigger */
34#define Dprintf(...)
3535
3636
37#define Dprintf(...)
37#define MAX_LATENCY 8 /* maximum latency; okay to make this bigger */
38
39#define FIELD(w) (((pfpu_instruction *) &(w))->i)
3840
3941
4042struct list {
...... 
9193
9294
9395/*
94 * Use naming conventions of include/linux/list.h
96 * Use the naming conventions of include/linux/list.h
9597 */
9698
9799static void list_init(struct list *list)
...... 
168170    int refs; /* usage count */
169171} *regs;
170172
171static struct list pfpu_regs[PFPU_REG_COUNT];
173static struct pfpu_reg {
174    struct list more; /* list of unallocated PFPU registers */
175    int vm_reg; /* corresponding FPVM register if allocated */
176    int used; /* used somewhere in the program */
177} pfpu_regs[PFPU_REG_COUNT];
178
172179static struct list unallocated; /* unallocated registers */
173180static int nbindings; /* "public" bindings */
174181
...... 
181188
182189static int alloc_reg(struct insn *setter)
183190{
184    struct list *reg;
191    struct pfpu_reg *reg;
185192    int vm_reg, pfpu_reg, vm_idx;
186193
187194    vm_reg = setter->vm_insn->dest;
...... 
190197    reg = list_pop(&unallocated);
191198    if (!reg)
192199        abort();
200    reg->vm_reg = vm_reg;
193201    pfpu_reg = reg-pfpu_regs;
194202Dprintf(" alloc reg %d -> %d\n", vm_reg, pfpu_reg);
195203    vm_idx = reg2idx(vm_reg);
...... 
200208}
201209
202210
203static void put_reg(struct insn *setter)
211static void put_reg(int vm_reg)
204212{
205    int vm_reg, vm_idx;
206
207    if (!setter)
208        return;
213    int vm_idx;
209214
210    vm_reg = setter->vm_insn->dest;
211215    if (vm_reg >= 0)
212216        return;
213217
...... 
220224     * Prepend so that register numbers stay small and bugs reveal
221225     * themselves more rapidly.
222226     */
223    list_add(&unallocated, pfpu_regs+regs[vm_idx].pfpu_reg);
227    list_add(&unallocated, &pfpu_regs[regs[vm_idx].pfpu_reg].more);
224228
225229    /* clear it for style only */
226230    regs[vm_idx].setter = NULL;
...... 
228232}
229233
230234
235static void put_reg_by_setter(struct insn *setter)
236{
237    if (setter)
238        put_reg(setter->vm_insn->dest);
239}
240
241
231242static int lookup_pfpu_reg(int vm_reg)
232243{
233244    return vm_reg >= 0 ? vm_reg : regs[reg2idx(vm_reg)].pfpu_reg;
234245}
235246
236247
248static void mark(int vm_reg)
249{
250    if (vm_reg > 0)
251        pfpu_regs[vm_reg].used = 1;
252}
253
254
237255static void init_registers(struct fpvm_fragment *fragment,
238256    unsigned int *registers)
239257{
...... 
247265    regs = malloc(regs_size);
248266    memset(regs, 0, regs_size);
249267
250    list_init(&unallocated);
251    for (i = fragment->nbindings; i != PFPU_REG_COUNT; i++)
252        list_add_tail(&unallocated, pfpu_regs+i);
268    memset(pfpu_regs, 0, sizeof(pfpu_regs));
269    for (i = 0; i != fragment->ninstructions; i++) {
270        mark(fragment->code[i].opa);
271        mark(fragment->code[i].opb);
272        mark(fragment->code[i].dest);
273    }
253274
254/*
255 * @@@ the rules are more complex, see use of dont_touch in
256 * init_scheduler_state
257 */
275    list_init(&unallocated);
276    for (i = PFPU_SPREG_COUNT; i != PFPU_REG_COUNT; i++)
277        if (!pfpu_regs[i].used)
278            list_add_tail(&unallocated, &pfpu_regs[i].more);
258279}
259280
260281
...... 
264285static struct list unscheduled; /* unscheduled insns */
265286static struct list waiting; /* insns waiting to be scheduled */
266287static struct list ready[PFPU_PROGSIZE]; /* insns ready at nth cycle */
267static struct insn *exits[PFPU_PROGSIZE+MAX_LATENCY];
268                    /* insn writing at nth cycle */
269static struct insn dummy_insn; /* dummy, to signal occupancy */
270288
271289
272290static struct vm_reg *add_data_ref(struct insn *insn, struct data_ref *ref,
...... 
335353            list_add_tail(&unscheduled, &insn->more);
336354        else
337355            list_add_tail(&ready[0], &insn->more);
338
339356    }
340
341    /*
342     * We add a few dummy instructions at the end so that we don't need to
343     * check array boundaries for the unlikely case of overrunning the
344     * schedule.
345     */
346    for (i = 0; i != PFPU_PROGSIZE; i++)
347        exits[i] = NULL;
348    for (; i != PFPU_PROGSIZE+MAX_LATENCY; i++)
349        exits[i] = &dummy_insn;
350357}
351358
352359
353static unsigned issue(struct insn *insn, int cycle)
360static void issue(struct insn *insn, int cycle, unsigned *code)
354361{
355    pfpu_instruction code;
356362    struct data_ref *ref;
357363    int end;
358int nada = 0;
359364    end = cycle+insn->latency;
360    exits[end] = insn;
361365
362366Dprintf("cycle %d: insn %lu L %d (A %d B %d)\n",
363367  cycle, insn-insns, insn->latency, insn->vm_insn->opa, insn->vm_insn->opb);
...... 
365369    case 3:
366370        /* fall through */
367371    case 2:
368        code.i.opb = lookup_pfpu_reg(insn->vm_insn->opb);
369        put_reg(insn->opb.dep);
372        FIELD(code[cycle]).opb = lookup_pfpu_reg(insn->vm_insn->opb);
373        put_reg_by_setter(insn->opb.dep);
370374        /* fall through */
371375    case 1:
372        code.i.opa = lookup_pfpu_reg(insn->vm_insn->opa);
373        put_reg(insn->opa.dep);
376        FIELD(code[cycle]).opa = lookup_pfpu_reg(insn->vm_insn->opa);
377        put_reg_by_setter(insn->opa.dep);
374378        break;
375379    case 0:
376380        break;
...... 
378382        abort();
379383    }
380384
381    code.i.dest = alloc_reg(insn);
382    code.i.opcode = fpvm_to_pfpu(insn->vm_insn->opcode);
385    FIELD(code[end]).dest = alloc_reg(insn);
386    FIELD(code[cycle]).opcode = fpvm_to_pfpu(insn->vm_insn->opcode);
383387
384388    foreach (ref, &insn->dependants) {
385389        if (ref->insn->earliest <= end)
386390            ref->insn->earliest = end+1;
387391        if (!--ref->insn->unresolved) {
388392Dprintf(" unlocked %lu -> %u\n", ref->insn-insns, ref->insn->earliest);
389nada = 0;
390393            list_del(&ref->insn->more);
391394            list_add_tail(ready+ref->insn->earliest,
392395                &ref->insn->more);
393396        }
394397    }
395if (nada && catch) *(volatile int *) 0 = 1;
396
397    return code.w;
398398}
399399
400400
...... 
423423  count(&waiting), count(&ready[i]));
424424        list_concat(&waiting, &ready[i]);
425425Dprintf("%d\n", count(&waiting));
426        foreach (insn, &waiting)
427            if (!exits[i+insn->latency]) {
428                code[i] = issue(insn, i);
426        foreach (insn, &waiting) {
427            end = i+insn->latency;
428            if (end >= PFPU_PROGSIZE)
429                return -1;
430            if (!FIELD(code[end]).dest) {
431                issue(insn, i, code);
429432                list_del(&insn->more);
430433                remaining--;
431434                break;
432435            }
433        if (exits[i])
434            put_reg(exits[i]);
436        }
437        if (FIELD(code[i]).dest)
438            put_reg(pfpu_regs[FIELD(code[i]).dest].vm_reg);
435439    }
436440
437441    /*
...... 
442446    if (end > PFPU_PROGSIZE)
443447        end = PFPU_PROGSIZE;
444448    while (i != end) {
445        if (exits[i])
449        if (FIELD(code[i]).dest)
446450            last = i+1; /* @@@ ? */
447451        i++;
448452    }

Archive Download the corresponding diff file

Branches:
master



interactive