microasm.awk
download
# Poniżej zamieszczam skrypt napisany przeze mnie na drugim roku studiów
# w ramach laboratoriów z techniki cyfrowej. Należało zaprojektować
# system cyfrowy oparty na mikrokodzie. Studenci dostali specyfikację
# INTEL HEX formatu danych do wczytania do epromu. Do wyliczania
# korzystali z kalkulatorów.
#
# Ponieważ jestem programistą z zamiłowania, to uznałem, że zadanie
# powinna być wsparte przez komputer. Napisałem mikroasembler, który
# automatycznie allokował adresy i rejestry oraz generował format potrzebny
# do programatora (zliczał także sumę kontrolną). Pozwoliło mi to na
# wygodne zaprojektowanie algorytmu.
#
# Składnia wejściowa dla asemblera:
#
# BEGIN: !s A.LE B.LE L1.LE W.CE BEGIN
# L01: B.Z EL01
# !B[0] EIF01
# 0 W.LE -
# EIF01: 1 A.SE B.SE L01
# EL01: 0 L1.EN M.S -
# L03: W<L1 EL03
# 1 W.LE M.S L03
# EL03: s r EL03
# 1 BEGIN
#
# Wynik działania skryptu został wygenerowany zdalnie na maszynie
# UNIX-owej (na Macintoshach nie mieliśmy shella ani narzędzia awk):
#
# :03000000F000000D
# :03000100052000D7
# :03000200044000B7
# :0300030000610099
# :0300040001860072
# :0300050000780080
# :0300060008A0004F
# :030007000691005F
# :0300080008E0000D
# :0300090000800074
# :00000001FF
#
# Projekt oczywiście zamknąłem maksymalną liczbą punktów.
# Poniżej treść skryptu.
#!/bin/awk -f
# program przetwarza wsadowo asembler mikrokodu i wypisuje skoplilowana
# tablice, ktora mozna wpisac do RAM
#
# postac:
# etykieta,predykat,akcja akcja ...,skok
# dozwolone komanetarze with #
# puste linie ignorowane
# pobranie bitu o numerze b ze slowa a
function bit(a,b, tmp)
{
tmp = int(a/(2^b));
return (tmp==int(tmp/2)*2)?0:1
}
function error(co)
{
print co
exit(1);
}
function set_bit(a,nr)
{
if(bit(a,nr)) return a
a+=2^nr
return a
}
function rights(a,i,ile)
{
return substr(a,length(a)-i,ile)
}
BEGIN{
# ostatni nie uzywany rekord
PC=0
#delete tab # tablica danych, gdzie wczytujemy program
#delete labels # tablica labels["LAB"]=PC
#delete pred # tablica predykatow pred["a"]=n_pred++
#delete pred_nr # pred_nr[n_pred++]="!a"
n_pred=0 # wolny numer predykatu
#delete data # tablica danych zapisanych binarnie
data_ile=0 # ile bitow na wiersz ?
# pola w rekordzie tablicy
LABEL=1
PRED=2
ACTION=3
JUMP=4
# tablica wyjsc postaci wyj["a3"]=3
# wartosc to offset bitu w slowie sterowania Y
#delete wyj
#delete wyj_nr
n_wyj=0 # wolna wartosc do przydzialu
}
/^#/ || ($0 ~ /^[\t ]*$/){
next
}
function add_predicate(p ,i)
{
if(pred[p]!="") return pred[p]
pred[p]=n_pred
pred_nr[n_pred]=p
return n_pred++
}
{
n=1;
ile=NF
split($0,A)
#print
# label
# print rights(A[n],0,1)
if(rights(A[n],0,1)==":")
{
tab[PC,LABEL] = substr(A[n],1,length(A[n])-1)
labels[tab[PC,LABEL]] = PC
n++
}
# predicate
tab[PC,PRED]=add_predicate(A[n])
n++
# operacje
maska=0
for(i=n;i<=ile-1;i++)
{
nr = wyj[A[i]]
if(nr=="")
{
nr = wyj[A[i]] = n_wyj++
wyj_nr[nr]=A[i]
}
# nr zawiera aktualny numer
maska = set_bit(maska,nr)
}
tab[PC,ACTION] = maska
# skok-gdzie
tab[PC,JUMP] = A[ile]
PC++
}
function find_label(s ,code)
{
if(s=="-") return 0
code = labels[s]
if(code=="")
{
printf("error: can't find label %s in code\n",s)
}
return code
}
function compile( code)
{
for(i=0;i<PC;i++)
{
code=find_label(tab[i,JUMP])
tab[i,JUMP] = code
}
}
function log2(x ,licz)
{
licz=0;
while(x)
{
x=int(x/2)
licz++
}
return licz
}
function decorate()
{
printf("*** ");
}
function show_tables( i,ile)
{
print ""
ile=log2(n_pred)-1
decorate()
printf "PREDICATS (%d bits: %d..%d):\n",
ile+1,
ile_jump+ile_act+ile_pred-1 ,ile_jump+ile_act
for(i=0;i<n_pred;i++)
{
printf("%s\t= ",pred_nr[i])
out_bin(i,ile)
printf "\n"
}
decorate()
printf "OUTPUTS (%d bits):\n",n_wyj
for(i=0;i<n_wyj;i++)
{
printf("%s\t= %d",wyj_nr[i],i)
printf(" (%d)\n",i+ile_jump);
}
}
function out_bin(a,max ,n)
{
for(n=max;n>-1;n--)
if(bit(a,n)) printf("1")
else printf("0")
}
function out_hex(a,ile)
{
while(ile)
{
printf( "%X",int(a/(16^(ile-1)))%16 );
ile--
}
}
function show_binary( pc,i)
{
print ""
for(pc=0;pc<PC;pc++)
{
out_bin(tab[pc,PRED],ile_pred-1)
#printf(" ")
out_bin(tab[pc,ACTION],ile_act-1)
#printf(" ")
out_bin(tab[pc,JUMP],ile_jump-1)
printf("\n")
}
}
function show_intelhex(pc,
i,ile_pred,ile_act,ile_jump,a,p,bytes,n,kod,ile)
{
print ""
ile_pred = log2(n_pred)
ile_act = n_wyj
ile_jump = log2(PC-1)
ile = ile_pred+ile_act+ile_jump
if(ile<=8) bytes=1
else if(ile<=16) bytes=2
else if(ile<=24) bytes=3
else if(ile<=32) bytes=4
else error("too many data bytes" )
print ile,"bits used in program,","->",bytes,"bytes for code"
for(pc=0;pc<PC;pc++)
{
a=0
sum=0;
printf(":0%d",bytes)
sum+=bytes
out_hex(pc,4)
sum+=int(pc/256)
sum+=pc%256
# kod
out_hex(0,2)
a+=(tab[pc,PRED]*2^(ile_jump + ile_act))
a+=(tab[pc,ACTION]*2^(ile_jump))
a+=(tab[pc,JUMP]*2^(0))
int_table[pc]=a;
# wypisanie zawartosci pamieci
for(n=0;n<bytes;n++)
{
out_hex(a/(256^n),2)
}
for(n=0;n<bytes;n++)
{
sum+=int(a/(256^n))
}
sum=sum%256
out_hex((256-sum)%256,2)
printf("\n")
}
print ":00000001FF"
}
function show_int()
{
print ""
for(pc=0;pc<PC;pc++)
{
print int_table[pc]
}
}
END{
compile()
ile_pred = log2(n_pred)
ile_act = n_wyj
ile_jump = log2(PC-1)
show_tables()
show_binary()
show_intelhex()
show_int()
}