Blame |
Last modification |
View Log
| RSS feed
/*
* Project: S.Ha.R.K.
*
* Coordinators:
* Giorgio Buttazzo <giorgio@sssup.it>
* Paolo Gai <pj@gandalf.sssup.it>
*
* Authors :
* Paolo Gai <pj@gandalf.sssup.it>
* (see the web pages for full authors list)
*
* ReTiS Lab (Scuola Superiore S.Anna - Pisa - Italy)
*
* http://www.sssup.it
* http://retis.sssup.it
* http://shark.sssup.it
*/
/**
------------
CVS : $Id: step3.c,v 1.1 2004-07-05 14:17:15 pj Exp $
File: $File$
Revision: $Revision: 1.1 $
Last update: $Date: 2004-07-05 14:17:15 $
------------
**/
/*
* Copyright (C) 2000 Paolo Gai
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include "kernel/kern.h"
#include "string.h"
#include "ll/i386/x-dos.h"
#include "modules/rr.h"
#include "modules/dummy.h"
#include "modules/edf.h"
#include "modules/sem.h"
#include "modules/hartport.h"
#include "drivers/keyb.h"
#include "ctype.h"
#include "tune.h"
int ending
=0;
// Patterns
#define MAX_PATTERN 10000
int max_pattern
= 0;
TIME pattern_t
[MAX_PATTERN
];
TIME pattern_period
[MAX_PATTERN
];
TIME pattern_wcet
[MAX_PATTERN
];
TIME pattern_iter
[MAX_PATTERN
];
TIME pattern_value
[MAX_PATTERN
];
TIME pattern_penalty
[MAX_PATTERN
];
// Random load
int max_random
= 0;
TIME random_t
[MAX_PATTERN
];
TIME random_reldline
[MAX_PATTERN
];
TIME random_wcet
[MAX_PATTERN
];
int random_value
[MAX_PATTERN
];
int random_penalty
[MAX_PATTERN
];
// Bad load
int max_bad
= 0;
TIME bad_t
[MAX_PATTERN
];
TIME bad_reldline
[MAX_PATTERN
];
TIME bad_wcet
[MAX_PATTERN
];
int bad_value
[MAX_PATTERN
];
int bad_penalty
[MAX_PATTERN
];
#define WCET_SLACK 500
void tune_pattern
(void)
{
int i
,w
;
for (i
=0; i
<max_pattern
; i
++) {
place
(0,15);
cprintf
("Tuning index %d/%d.\n",i
,max_pattern
);
if (i
>0 && pattern_wcet
[i
]==pattern_wcet
[i
-1])
pattern_iter
[i
] = pattern_iter
[i
-1];
else {
w
= (pattern_wcet
[i
]*80)/100-WCET_SLACK
;
// if (w>pattern_wcet[i]-WCET_SLACK) w=pattern_wcet[i]-WCET_SLACK;
pattern_iter
[i
] = tune_CPU_speed
(w
);
}
}
}
// Shape modification
#define DEFAULT_SHIFT 1000000
#define MAX_SHAPE 1000
bandwidth_t shape_B
[MAX_SHAPE
];
TIME shape_T
[MAX_SHAPE
];
int max_shape
;
// this function creates a set if tasks (1 or 2) that comes at random
// time, with random values and random wcet.
#define MAX_PERIOD 2998
void generate_random_load
(void)
{
int current_time
= DEFAULT_SHIFT
;
while (current_time
<shape_T
[max_shape
-1]*1000000) {
random_t
[max_random
] = current_time
;
random_reldline
[max_random
] = rand()%MAX_PERIOD
*1000+2;
random_wcet
[max_random
] = rand()%(random_reldline
[max_random
]-1000)+1000;
random_value
[max_random
] = rand()%101;
random_penalty
[max_random
] = rand()%101;
if (rand()%2)
current_time
+= random_reldline
[max_random
] + 100000;
max_random
++;
}
}
#define MAX_VALUE_REL_DLINE 3000000
#define SUBTASKS 10
#define SUBSUBTASKS 30
void generate_bad_load
(void)
{
int i
,j
,k
;
bandwidth_t freeB
;
TIME t
,l
;
int subtasks
, rdline
;
for (i
=1; i
< max_shape
; i
++) {
//length of the period with the same max bandwidth
l
= (shape_T
[i
]-shape_T
[i
-1])* 1000000;
freeB
= MAX_BANDWIDTH
- shape_B
[i
-1];
t
= shape_T
[i
-1]*1000000 + DEFAULT_SHIFT
;
if (l
/SUBTASKS
> MAX_VALUE_REL_DLINE
) {
subtasks
= l
/MAX_VALUE_REL_DLINE
;
rdline
= MAX_VALUE_REL_DLINE
;
}
else {
subtasks
= SUBTASKS
;
rdline
= l
/SUBTASKS
;
}
for (j
=0; j
<subtasks
; j
++) {
// create the first "big" task
bad_t
[max_bad
] = t
;
bad_reldline
[max_bad
] = rdline
;
bad_wcet
[max_bad
] = (int)(((double)freeB
/(double)MAX_BANDWIDTH
)*bad_reldline
[max_bad
]);
bad_value
[max_bad
] = 80;
bad_penalty
[max_bad
] = 90;
max_bad
++;
// create the small subtasks!!
for (k
=0; k
<SUBSUBTASKS
; k
++) {
bad_t
[max_bad
] = t
;
bad_reldline
[max_bad
] = rdline
/SUBSUBTASKS
;
bad_wcet
[max_bad
] = (int)(((double)freeB
/(double)MAX_BANDWIDTH
)*bad_reldline
[max_bad
]);
bad_value
[max_bad
] = 100/SUBSUBTASKS
;
bad_penalty
[max_bad
] = 200/SUBSUBTASKS
;
max_bad
++;
t
+= rdline
/SUBSUBTASKS
;
}
}
}
}
#define INSERT_RANDOM 1
#define INSERT_BAD 2
// This function merges the random load and the bad_load into the pattern!
// This function subsumes that the two arrays are ordered by time.
void generate_pattern
(void)
{
int random_i
, bad_i
;
int todo
= 0;
random_i
= 0;
bad_i
= 0;
while (!(random_i
== max_random
&& bad_i
== max_bad
)) {
if (random_i
< max_random
) {
// there are random available
if (bad_i
< max_bad
)
// random and bad available
if (random_t
[random_i
] < bad_t
[bad_i
])
todo
= INSERT_RANDOM
;
else
todo
= INSERT_BAD
;
else
// only random
todo
= INSERT_RANDOM
;
}
else
// only bad available
todo
= INSERT_BAD
;
if (todo
== INSERT_RANDOM
) {
pattern_t
[max_pattern
] = random_t
[random_i
];
pattern_period
[max_pattern
] = random_reldline
[random_i
];
pattern_wcet
[max_pattern
] = random_wcet
[random_i
];
pattern_value
[max_pattern
] = random_value
[random_i
];
pattern_penalty
[max_pattern
] = random_penalty
[random_i
];
max_pattern
++;
random_i
++;
}
else {
pattern_t
[max_pattern
] = bad_t
[bad_i
];
pattern_period
[max_pattern
] = bad_reldline
[bad_i
];
pattern_wcet
[max_pattern
] = bad_wcet
[bad_i
];
pattern_value
[max_pattern
] = bad_value
[bad_i
];
pattern_penalty
[max_pattern
] = bad_penalty
[bad_i
];
max_pattern
++;
bad_i
++;
}
}
}
// Read/Write part
#define FILEBUF_DIM 10000
/* This is the buffer used by read_myfile */
char myfilebuf
[FILEBUF_DIM
];
/* This is the number of bytes read by read_myfile */
int myfilebuf_length
;
/* the buffer b is scannedc to search for numbers
at the first non-number the function stops */
int geti
(char *b
, int *pos
, int maxpos
)
{
int res
= 0;
// skip first chars
while (!isdigit(b
[*pos
])) {
(*pos
)++;
if (*pos
== maxpos
) return -1; // Error!!!
}
// read the numbers
do {
res
= (res
* 10) + b
[*pos
] - '0';
(*pos
)++;
} while (isdigit(b
[*pos
]));
return res
;
}
void parse_shape
(void)
{
int curr_filepos
= 0;
int i
= 0;
// read the number of tasks into the data file
max_shape
= geti
(myfilebuf
, &curr_filepos
, myfilebuf_length
);
if (max_shape
== -1) {
cprintf
("Error parsing shape.dat file...\n");
sys_end
();
}
for (i
=0; i
<max_shape
; i
++) {
// read the seven datas
shape_T
[i
] = geti
(myfilebuf
, &curr_filepos
, myfilebuf_length
);
shape_B
[i
] = geti
(myfilebuf
, &curr_filepos
, myfilebuf_length
);
// check the last one for an error
if (shape_B
[i
] == -1) {
cprintf
("Error parsing shape %d...\n",i
);
sys_end
();
}
}
}
void read_shapes
(void)
{
char name
[]="shape.dat";
/* DOS file descriptor */
DOS_FILE
*f
;
/* Error code */
int err
;
/* open the DOS file for reading (you can specify only "r" or "w") */
f
= DOS_fopen
(name
,"r");
/* check for open errors */
if (!f
) {
/* error!! */
err
= DOS_error
();
/* note that if you call DOS_error() here, it return 0!!! */
cprintf
("Error %d opening %s...\n", err
, name
);
myfilebuf_length
= 0;
return;
}
/* read up to 1000 chars */
myfilebuf_length
= DOS_fread
(&myfilebuf
,1,FILEBUF_DIM
,f
);
/* check for errors */
err
= DOS_error
();
cprintf
("Read %d bytes from %s...\n", myfilebuf_length
, name
);
if (err
) {
cprintf
("Error %d reading %s...\n", err
, name
);
myfilebuf_length
= 0;
/* there is not return because I want to close the file! */
}
/* Close the file */
DOS_fclose
(f
);
}
/* This function write myfile.out (up to 30 chars) */
void write_vpattern
(void *arg
)
{
DOS_FILE
*f
; /* DOS file descriptor */
int err
=0; /* Error code */
int writtenbytes
= 0; /* number of files written */
char buf
[100];
int i
;
/* open the DOS file for writing (you can specify only "r" or "w") */
f
= DOS_fopen
("vpattern.dat","w");
/* check for open errors */
if (!f
) {
/* error!! */
err
= DOS_error
();
/* note that if you call DOS_error() here, it return 0!!! */
cprintf
("Error %d opening hpattern.dat...\n", err
);
return;
}
sprintf(buf
,"%d\r\n",max_pattern
);
writtenbytes
+= DOS_fwrite
(buf
,1,strlen(buf
),f
);
for (i
=0; i
<max_pattern
; i
++) {
sprintf(buf
,"%ld %ld %ld %ld %ld %ld\r\n",
pattern_t
[i
],
pattern_period
[i
],
pattern_wcet
[i
],
pattern_iter
[i
],
pattern_value
[i
],
pattern_penalty
[i
]);
writtenbytes
+= DOS_fwrite
(buf
,1,strlen(buf
),f
);
/* check for errors */
err
= DOS_error
();
if (err
) break;
}
cprintf
("Written %d bytes into vpattern.dat...\n", writtenbytes
);
if (err
) {
cprintf
("Error %d writing vpattern.dat...\n", err
);
/* there is not return because I want to close the file! */
}
/* Close the file */
DOS_fclose
(f
);
}
/*+ sysyem tick in us +*/
#define TICK 0
/*+ RR tick in us +*/
#define RRTICK 10000
void read_myfile
(void);
TIME __kernel_register_levels__
(void *arg
)
{
struct multiboot_info
*mb
= (struct multiboot_info
*)arg
;
EDF_register_level
(EDF_ENABLE_ALL
);
RR_register_level
(RRTICK
, RR_MAIN_NO
, mb
);
RR_register_level
(RRTICK
, RR_MAIN_YES
, mb
);
dummy_register_level
();
SEM_register_module
();
read_shapes
();
return TICK
;
}
NRT_TASK_MODEL keyb_model
;
TASK __init__
(void *arg
)
{
KEYB_PARMS kparms
= BASE_KEYB
;
HARTPORT_init
();
nrt_task_default_model
(keyb_model
);
nrt_task_def_system
(keyb_model
);
nrt_task_def_nokill
(keyb_model
);
keyb_def_task
(kparms
,(TASK_MODEL
*)&keyb_model
);
KEYB_init
(&kparms
);
set_exchandler_grx
();
srand(sys_gettime
(NULL
));
clear
();
sys_atrunlevel
(write_vpattern
, NULL
, RUNLEVEL_AFTER_EXIT
);
parse_shape
();
// random load...
generate_random_load
();
// a big task and a lot of small tasks that uses 2*(MAX_BANDWIDTH-shape)
generate_bad_load
();
// mixes the two loads
generate_pattern
();
tune_pattern
();
return (void *)0;
}
// never called!!!
int main
()
{
return 0;
}