syn68k/runtime/sched.pl

320 lines
6.5 KiB
Perl
Executable File

#!/usr/bin/perl
require "x86_recog.pl";
sub intersect {
local (@sets) = @_;
local ($set, $elem);
local (%mark);
foreach $set (@sets) {
foreach $elem (split (' ', $set))
{
local (@keys);
$mark{$elem} = $mark{$elem};
@keys = keys %mark;
grep (do { $mark{$_}++ if /$elem/; }, @keys);
grep (do { $mark{$elem}++ if $elem =~ /$_/; }, @keys);
$mark{$elem}--;
# grep (do { $mark{$elem}-- if $elem eq $_; }, @keys);
}
}
return &union (join (' ', grep ($mark{$_} >= @sets, keys (%mark))));
}
sub union {
local (@sets) = @_;
local (@from, @to);
local ($elem);
@from = split (' ', join (' ', @sets));
while ($elem = shift @from)
{
next if grep ($elem =~ /$_/, @from);
next if grep ($elem =~ /$_/, @to);
push (@to, $elem);
}
return join (' ', sort (@to));
}
sub is_subset {
local ($little, $big) = @_;
return ($little eq &intersect ($little, $big));
}
sub make_parents {
local($lineno, $earlier);
local($seeking, $not_seeking, $found);
foreach $lineno ($first_line .. $last_line)
{
local (*par_ref) = 'parents' . $lineno;
@par_ref = ();
undef $not_seeking;
$seeking = $inputs[$lineno];
next if (!$seeking);
foreach $earlier (reverse ($first_line .. $lineno-1))
{
$found = &intersect ($seeking, $outputs[$earlier]);
next if (&is_subset ($found, $not_seeking));
$not_seeking = &union ($not_seeking, $found);
if ($found) {
#print $lineno . " " . $earlier . "\n";
push (@par_ref, $earlier);
}
}
}
}
sub bad_order {
local ($first, $middle, $last) = @_;
if (($first < $middle) && ($middle < $last)) {
return 0;
}
if (!defined ($cached_bad{$first, $middle, $last})) {
if (&intersect ($outputs[$first],
&intersect($outputs[$middle],
$inputs[$last])))
{
$cached_bad{$first, $middle, $last} = 1;
}
else
{
$cached_bad{$first, $middle, $last} = 0;
}
}
return $cached_bad{$first, $middle, $last};
}
sub max
{
local (@values) = @_;
local ($result);
grep (do { $result = $_ if $result < $_ } && 0, @values);
return $result;
}
sub static_eval {
return ($start_time[$schedule[$#schedule]] + 1 + $last_line -
$first_line + 1 - @schedule);
}
sub push_schedule {
local ($lineno) = @_;
local (@parents_times);
local ($parent);
if ($lineno == 0)
{
$start_time[$lineno] = 0;
}
else
{
local (*par_ref) = 'parents' . $lineno;
foreach $parent (@par_ref)
{
push (@parents_times, $start_time[$parent] + $latency[$parent]);
}
$start_time[$lineno] = &max ($start_time[$schedule[$#schedule]] + 1,
@parents_times);
}
push (@schedule, $lineno);
}
sub pop_schedule {
pop (@schedule);
}
sub dump_schedule
{
local ($lineno);
foreach $lineno (@_)
{
print "$lines[$lineno]\t; $start_time[$lineno]\n"
}
}
sub create_greedy_lookup
{
local (@which_lines) = @_;
local ($lineno);
foreach $lineno (@which_lines)
{
&push_schedule ($lineno);
$greedy_lookup[$lineno] = &static_eval ();
&pop_schedule ();
}
}
sub bygreed
{
local ($foo);
$foo = $greedy_lookup[$a] <=> $greedy_lookup[$b];
return ($a <=> $b) if (!$foo);
return $foo;
}
sub parents_scheduled
{
local ($lineno) = @_;
local (*par_ref) = 'parents' . $lineno;
return !grep (!$scheduled[$_], @par_ref);
}
sub create_schedule {
local ($lineno, $unscheduled_line);
local ($static_value);
local (@valid_next_lines);
local (@unscheduled);
local (@possible_problems);
return if ($best_so_far == $last_line - $first_line + 1);
$static_value = &static_eval();
return if ($static_value >= $best_so_far);
if (@schedule == $last_line - $first_line + 1)
{
# &dump_schedule (@schedule);
# print " Value: $static_value\n";
if ($static_value <= $best_so_far)
{
@best_schedule = @schedule;
$best_so_far = $static_value;
}
return;
}
@unscheduled = grep (!$scheduled[$_], ($first_line .. $last_line));
@valid_next_lines = grep (&parents_scheduled ($_), @unscheduled);
&create_greedy_lookup (@valid_next_lines);
foreach $lineno (sort bygreed (@valid_next_lines))
{
local ($bad);
$bad = 0;
foreach $unscheduled_line (@unscheduled)
{
local ($possible_problem);
local (*par_ref) = 'parents' . $unscheduled_line;
next if $unscheduled_line == $lineno;
@possible_problems = grep ($scheduled[$_], @par_ref);
foreach $possible_problem (@possible_problems)
{
next if (!&bad_order ($possible_problem, $lineno,
$unscheduled_line));
$bad = 1;
last;
}
last if $bad;
}
next if $bad;
&push_schedule ($lineno);
$scheduled[$lineno] = 1;
&create_schedule ();
&pop_schedule ();
$scheduled[$lineno] = 0;
}
}
@parents0 = @parents1 = @parents2 = @parents3 = ();
@parents4 = @parents5 = @parents6 = @parents7 = ();
@parents8 = @parents9 = @parents10 = @parents11 = ();
while (<>) {
next if /^\s*$/;
next if /^#(NO_)?APP/;
if (!@lines && /^\s*\./)
{
print;
next;
}
chop;
if (!@lines) {
# Prepend a dummy instruction
push (@lines, '@@@@bogo@@@@');
$inputs[$#lines] = "";
$outputs[$#lines] = "";
$latency[$#lines] = 0;
}
push (@lines, $_);
($inputs[$#lines], $outputs[$#lines], $latency[$#lines]) =
&recognize ($_);
if (@lines >= 10 || eof() || $inputs[$#lines] eq '.*'
|| $outputs[$#lines] =~ /eip/)
{
local ($saved_outputs);
$saved_outputs = $outputs[0];
$outputs[0] = '.*';
# Append a dummy instruction
push (@lines, '@@@@bogo@@@@');
$inputs[$#lines] = ".*";
$outputs[$#lines] = ".*";
$latency[$#lines] = 0;
$first_line = 0;
$last_line = $#lines;
&make_parents ();
$best_so_far = 999999;
undef %cached_bad;
undef @schedule;
undef @start_time;
undef @best_schedule;
undef @scheduled;
# print "\nInput block:\n", join ("\n", @lines), "\n";
&create_schedule ();
# print "\nOutput block:\n", join ("\n", @lines[@best_schedule]), "\n\n";
$outputs[0] = $saved_outputs;
# Renumber everything
@lines = @lines[@best_schedule];
@inputs = @inputs[@best_schedule];
@outputs = @outputs[@best_schedule];
@latency = @latency[@best_schedule];
while ($line = shift @lines)
{
local ($foo, $bar);
$foo = shift @inputs;
$bar = shift @outputs;
shift @latency;
print "$line\n" if ($line !~ /\@\@\@\@bogo\@\@\@\@/);
print STDERR "$line\n" if ($line =~ /^\w*:\s*$/);
# print " Inputs: $foo\n Outputs: $bar\n";
# last if ((@lines <= 5) && !eof() && !($inputs[$#lines] eq '.*'));
}
}
}