#include "synthesize.h" #include int zzzwire_zaehler=0; int bind_zaehler=0; struct stringlisten_eintrag *hdl_code; struct stringlisten_eintrag *hdl_code_deklarationen; struct stringlisten_eintrag *hdl_code_zuweisungen; // integriert die konstanten Parameter in den Modulnamen struct stringlisten_eintrag *integrate_constants(struct funktionslisten_eintrag *funktion,struct knoten *knot,int *paraanzahl,struct parameter_typ **parameterarray,struct stringlisten_eintrag *aktpos) { struct stringlisten_eintrag *strtemp=aktpos; struct knoten *temp; int parameteranzahl=0; int i; // zuerst die Anzahl der Parameter bestimmen temp=knot->sub[1]->sub[0]; if (temp->subtyp==245) // expr_leerlist => expr_list { temp=temp->sub[0]; while (temp->subtyp==247) // expr_list => expr ',' expr_list { parameteranzahl++; temp=temp->sub[1]; } temp->sub[0]=vereinfache_expression(temp->sub[0]); parameteranzahl++; } *paraanzahl=parameteranzahl; *parameterarray=(struct paramter_typ *) malloc (parameteranzahl*sizeof(struct parameter_typ)); allokierter_speicher+=parameteranzahl*sizeof(struct parameter_typ); // Die Parameter fuer die Funktion durchgehen und testen ob sie konstant sind i=0; temp=knot->sub[1]->sub[0]; if (temp->subtyp==245) // expr_leerlist => expr_list { temp=temp->sub[0]; // gehe die expr_list durch while (temp->subtyp==247) // expr_list => expr ',' expr_list { temp->sub[0]=vereinfache_expression(temp->sub[0]); // falls es eine Konstante ist, diese einfuegen (*parameterarray)[i].is_constant=0; (*parameterarray)[i].name=NULL; (*parameterarray)[i].typ=3; if (is_constant(temp->sub[0])) { (*parameterarray)[i].is_constant=1; (*parameterarray)[i].wert=expression_ausrechnen(temp->sub[0]); strtemp=stringlist_einfuegen(strtemp,"_"); strtemp=synthesize_expression(funktion,temp->sub[0],strtemp); } i++; temp=temp->sub[1]; } // nun die letzte Expression in der Expressionlist bearbeiten temp->sub[0]=vereinfache_expression(temp->sub[0]); (*parameterarray)[i].is_constant=0; (*parameterarray)[i].name=NULL; (*parameterarray)[i].typ=3; if (is_constant(temp->sub[0])) { (*parameterarray)[i].is_constant=1; (*parameterarray)[i].wert=expression_ausrechnen(temp->sub[0]); (*parameterarray)[i].typ=3; strtemp=stringlist_einfuegen(strtemp,"_"); strtemp=synthesize_expression(funktion,temp->sub[0],strtemp); } } return strtemp; } // uebersetzt ein IF (subtyp 218) : d.h. expr -> IF expr THEN expr ELSE expr ENDIF struct stringlisten_eintrag *synthesize_if218(struct funktionslisten_eintrag *funktion,struct knoten *knot,struct stringlisten_eintrag *akt_position) { struct stringlisten_eintrag *strtemp=akt_position; // Erst die Bedingung strtemp=stringlist_einfuegen(strtemp,"("); strtemp=synthesize_expression(funktion,knot->sub[0],strtemp); strtemp=stringlist_einfuegen(strtemp,")"); strtemp=stringlist_einfuegen(strtemp," ? "); // 1. Konsequenz strtemp=stringlist_einfuegen(strtemp,"("); strtemp=synthesize_expression(funktion,knot->sub[1],strtemp); strtemp=stringlist_einfuegen(strtemp,")"); strtemp=stringlist_einfuegen(strtemp," : "); // 2. Konsequenz strtemp=stringlist_einfuegen(strtemp,"("); strtemp=synthesize_expression(funktion,knot->sub[2],strtemp); strtemp=stringlist_einfuegen(strtemp,")"); return strtemp; } // uebersetzt ein IF (subtyp 219) : d.h. expr -> IF expr1 THEN expr2 elseif_plus ELSE expr3 ENDIF struct stringlisten_eintrag *synthesize_if219(struct funktionslisten_eintrag *funktion,struct knoten *knot,struct stringlisten_eintrag *akt_position) { struct stringlisten_eintrag *strtemp=akt_position; // Erst die Bedingung strtemp=stringlist_einfuegen(strtemp,"("); strtemp=synthesize_expression(funktion,knot->sub[0],strtemp); strtemp=stringlist_einfuegen(strtemp,")"); strtemp=stringlist_einfuegen(strtemp," ? "); // 1. Konsequenz strtemp=stringlist_einfuegen(strtemp,"("); strtemp=synthesize_expression(funktion,knot->sub[1],strtemp); strtemp=stringlist_einfuegen(strtemp,")"); strtemp=stringlist_einfuegen(strtemp," : "); // 2. Konsequenz ( der ELSIF-Teil mit expr3 als Elseteil) strtemp=stringlist_einfuegen(strtemp,"("); strtemp=synthesize_elseif(funktion,knot->sub[2],knot->sub[3],strtemp); strtemp=stringlist_einfuegen(strtemp,")"); return strtemp; } // uebersetzt den ELSIF-Teil eines IF (Subtyp 219) bzw. den ELSIF-Teil eines ELSIF; der else-Teil des IF (219) wird hier uebersetzt struct stringlisten_eintrag *synthesize_elseif(struct funktionslisten_eintrag *funktion,struct knoten *knot,struct knoten *else_teil,struct stringlisten_eintrag *aktpos) { struct stringlisten_eintrag *strtemp=aktpos; // Erst die Bedingung strtemp=stringlist_einfuegen(strtemp,"("); strtemp=synthesize_expression(funktion,knot->sub[0],strtemp); strtemp=stringlist_einfuegen(strtemp,")"); strtemp=stringlist_einfuegen(strtemp," ? "); // 1. Konsequenz strtemp=stringlist_einfuegen(strtemp,"("); strtemp=synthesize_expression(funktion,knot->sub[1],strtemp); strtemp=stringlist_einfuegen(strtemp,")"); strtemp=stringlist_einfuegen(strtemp," : "); // Fallunterscheidung if (knot->subtyp==242) { // 1.Fall : Subtyp 242 : elseif_plus -> ELSIF expr THEN expr // es fehlt noch der else-Teil des uebergeordneten IF strtemp=stringlist_einfuegen(strtemp,"("); strtemp=synthesize_expression(funktion,else_teil,strtemp); strtemp=stringlist_einfuegen(strtemp,")"); } else { // 2.Fall : Subtyp 243 : ELSIF expr THEN expr elseif_plus strtemp=stringlist_einfuegen(strtemp,"("); strtemp=synthesize_elseif(funktion,knot->sub[2],else_teil,strtemp); strtemp=stringlist_einfuegen(strtemp,")"); } return strtemp; } // übersetzt einen Funktionsaufruf struct stringlisten_eintrag *synthesize_funktionsaufruf(struct funktionslisten_eintrag *funktion,struct knoten *knot,struct stringlisten_eintrag *akt_position) { struct knoten *temp; struct knoten *temp2; int i; char chartemp[100]; struct stringlisten_eintrag *strtemp; struct stringlisten_eintrag *rstr=akt_position; struct stringlisten_eintrag *merkepos=akt_position; struct parameter_typ *parameterarray; int parameteranzahl; if ((knot->sub[0]->subtyp==159) // expr -> name && (knot->sub[0]->sub[0]->subtyp==347) // name_token -> idop && (knot->sub[0]->sub[0]->sub[0]->subtyp==331)) // idop -> ID { temp=knot->sub[0]->sub[0]->sub[0]->sub[0]; // den Zzzwire_Zaehler erhöhen zzzwire_zaehler++; // einen neuen wire deklarieren hdl_code_deklarationen=stringlist_einfuegen(hdl_code_deklarationen,"\twire zzz_wire_"); sprintf(chartemp,"%d",zzzwire_zaehler); hdl_code_deklarationen=stringlist_einfuegen(hdl_code_deklarationen,chartemp); hdl_code_deklarationen=stringlist_einfuegen(hdl_code_deklarationen,";\n"); // und dessen Namen an aktueller Stelle einfügen merkepos=stringlist_einfuegen(merkepos,"zzz_wire_"); merkepos=stringlist_einfuegen(merkepos,chartemp); // dann am Ende des Moduls eine neue Zeile fuer den Funktionsaufruf einfuegen // Modulenamen, Instanznamen ausgeben stringlist_append(hdl_code,"\n\t"); strtemp=stringlist_append(hdl_code,temp->wert_str); // dabei die konstanten Parameter in den Funktionsnamen integrieren und gleichzeitig eine Liste mit den Parametern // anlegen, anhand derer man feststellen kann, welche Version der aufgerufenen Funktion (d.h. welche Konstanten, // z.B. lzeroimpl_16 or lzeroimpl_32 ) verwendet werden sollen // gehe dazu die expressions im Funktionsaufruf durch und teste mit backend.c/is_constant usw. ... strtemp=integrate_constants(funktion,knot,¶meteranzahl,¶meterarray,strtemp); // die aufgerufene Funktion der Liste mit den fehlenden Funktionen hinzufuegen, // damit sie spaeter auch synthetisiert werden kann funktionsliste_add(&fehlende_funktionen,temp->wert_str,NULL,funktion->var_list,parameteranzahl,parameterarray); // und dann noch einen Namen fuer diese Instanz stringlist_append(hdl_code," "); stringlist_append(hdl_code,temp->wert_str); // und einen Zzzwire_Zaehler dahinter, um eindeutige Namen zu haben stringlist_append(hdl_code,"_NR"); sprintf(chartemp,"%d",zzzwire_zaehler); stringlist_append(hdl_code,chartemp); stringlist_append(hdl_code," "); // Parameter ausgeben // zuerst den Rueckgabeparameter stringlist_append(hdl_code,"(zzz_wire_"); sprintf(chartemp,"%d",zzzwire_zaehler); strtemp=stringlist_append(hdl_code,chartemp); // dann die Eingabeparameter, die nicht konstant sind // die Konstanten Eingabeparameter wurden in den Funktionsnamen eingebunden // gehe dazu die Expressions im Funktionsaufruf durch und übersetze sie mit synthesize_expression temp=knot->sub[1]->sub[0]; if (temp->subtyp==245) // expr_leerlist => expr_list { temp=temp->sub[0]; while (temp->subtyp==247) // expr_list => expr ',' expr_list { if (!is_constant(temp->sub[0])) { strtemp=stringlist_einfuegen(strtemp,", "); strtemp=synthesize_expression(funktion,temp->sub[0],strtemp); } temp=temp->sub[1]; } if (!is_constant(temp->sub[0])) { strtemp=stringlist_einfuegen(strtemp,", "); strtemp=synthesize_expression(funktion,temp->sub[0],strtemp); } } // so, jetzt noch die Klammer zu strtemp=stringlist_append(hdl_code,");"); } else { printf ("Unbekanntes Konstrukt in synthesize-Funktionsaufruf.\n"); } return merkepos; } // benennt im zu knot gehoerenden Unterbaum die Variable altname in neuname um void konsistent_umbenennen(struct knoten *knot,char *altname,char *neuname) { int i; if ((knot->subtyp==159) // expr -> name && (knot->sub[0]->subtyp==347) // name -> idop && (knot->sub[0]->sub[0]->subtyp==331)) // idop -> ID { // wir haben einen Bezeichner, der evtl. umbenannt werden muss if (strcmp(altname,knot->sub[0]->sub[0]->sub[0]->wert_str)==0) { // dieser Bezeichner muss umbenannt werden // Speicher fuer alten Namen freigeben free_str(knot->sub[0]->sub[0]->sub[0]->wert_str); // neuen Namen speichern knot->sub[0]->sub[0]->sub[0]->wert_str=alloc_str(strlen(neuname)); strcpy(knot->sub[0]->sub[0]->sub[0]->wert_str,neuname); } } else { // Kein Bezeichner, d.h. alle Sub bearbeiten for (i=0;isubanz;i++) { konsistent_umbenennen(knot->sub[i],altname,neuname); } } } // verarbeitet ein einzelnes bind (d.h. ersetzt evtl. Konstanten und benennt konsistent um und fuegt die Definitionen fuer die // neuen Namen der umbenannten Variablen ein (d.h. welchen Wert hat die neue Variable) // ansonsten s. verarbeite_bindlist void verarbeite_bind(struct funktionslisten_eintrag *funktion,struct knoten *bindknoten,struct knoten *exprknoten) { struct konstante konstante; char *neuname; bind_zaehler++; if (bindknoten->subtyp==238) // bind => '(' simplebind_list ')' '=' expr { printf ("simplebind_listen werden nicht unterstuetzt\n"); exit (1); } if ((bindknoten->sub[0]->subtyp==302) // simplebind => idop && (bindknoten->sub[0]->sub[0]->subtyp==331)) // idop => id { konstante.name=bindknoten->sub[0]->sub[0]->sub[0]->wert_str; } else { printf ("Fehler bei Behandlung von simplebind\n"); exit(1); } if (is_constant(bindknoten->sub[1])) { // das bind ordnet der Zielvariablen einen konstanten Ausdruck zu konstante.wert=get_constant_value(bindknoten->sub[1]); ersetze_konstanten(exprknoten,1,&konstante); } else { // kein konstanter Ausdruck // Variablen umbenennen (s. fehlend.txt) // neuer Variablenname ist alter Variablenname mit eindeutiger Nummer bind_zaehler dahinter neuname=alloc_str(strlen(konstante.name)+(bind_zaehler/10+1)); strcpy(neuname,konstante.name); sprintf(neuname,"%s%d",neuname,bind_zaehler); // Definition des // "wire neuname = bindknoten->sub[1]" einfuegen hdl_code_deklarationen=stringlist_einfuegen(hdl_code_deklarationen,"\twire "); hdl_code_deklarationen=stringlist_einfuegen(hdl_code_deklarationen,neuname); hdl_code_deklarationen=stringlist_einfuegen(hdl_code_deklarationen," = "); hdl_code_deklarationen=synthesize_expression(funktion,bindknoten->sub[1],hdl_code_deklarationen); hdl_code_deklarationen=stringlist_einfuegen(hdl_code_deklarationen,";\n"); // Variablen konsistent umbenennen if (parameter_verbose) { printf ("Konsistente Umbenennung von %s nach %s\n",konstante.name,neuname); } konsistent_umbenennen(exprknoten,konstante.name,neuname); freigegebener_speicher+=strlen(neuname)+1; free(neuname); } } // verarbeitet eine Bind_list, indem bei konstanten binds die entsprechende Variable durch die Konstante ersetzt wird und // ansonsten ein neuer Wire deklariert wird // Parameter : // - bindlistknoten : der Wurzelknoten der bindlist-deklaration // - exprknoten : der Wurzelknoten der Expression, fuer die die binds gueltig sind void verarbeite_bindlist(struct funktionslisten_eintrag *funktion,struct knoten *bindlistknoten,struct knoten *exprknoten) { struct knoten *tempexprknoten=exprknoten; if (bindlistknoten->subtyp==240) { // SubTyp 240 : bind_list => bind verarbeite_bind(funktion,bindlistknoten->sub[0],tempexprknoten); } else { // SubTyp 241 : bind_list => bind_list ',' bind verarbeite_bindlist(funktion,bindlistknoten->sub[0],tempexprknoten); verarbeite_bind(funktion,bindlistknoten->sub[1],tempexprknoten); } } // übersetzt eine Expression struct stringlisten_eintrag *synthesize_expression(struct funktionslisten_eintrag *funktion,struct knoten *knot,struct stringlisten_eintrag *akt_position) { struct stringlisten_eintrag *strtemp=akt_position; char s[100]; int bearbeitet=0; switch (knot->subtyp) { case 157 : // expr -> NUMBER { sprintf(&s,"%d",knot->sub[0]->wert_int); strtemp=stringlist_einfuegen(strtemp,s); break; } case 167 : // expr -> expr funarg { strtemp=synthesize_funktionsaufruf(funktion,knot,strtemp); break; } case 159 : // expr -> name { if (knot->sub[0]->subtyp==347) // name -> idop { if (knot->sub[0]->sub[0]->subtyp==331) // idop -> ID { strtemp=stringlist_einfuegen(strtemp,knot->sub[0]->sub[0]->sub[0]->wert_str); bearbeitet=1; } else { if (knot->sub[0]->sub[0]->subtyp==332) // idop -> opsym { if (knot->sub[0]->sub[0]->sub[0]->subtyp==377) // opsym -> TRUE { strtemp=stringlist_einfuegen(strtemp,"1'b1"); bearbeitet=1; } if (knot->sub[0]->sub[0]->sub[0]->subtyp==378) // opsym -> FALSE { strtemp=stringlist_einfuegen(strtemp,"1'b0"); bearbeitet=1; } } } } if (bearbeitet==0) { strtemp=stringlist_einfuegen(strtemp,"!!! Unknown Expression !!!"); } break; } case 174 : // expr -> expr OR expr { strtemp=stringlist_einfuegen(strtemp,"("); strtemp=synthesize_expression(funktion,knot->sub[0],strtemp); strtemp=stringlist_einfuegen(strtemp," | "); strtemp=synthesize_expression(funktion,knot->sub[1],strtemp); strtemp=stringlist_einfuegen(strtemp,")"); break; } case 176 : case 178 : // expr -> expr & expr { strtemp=stringlist_einfuegen(strtemp,"("); strtemp=synthesize_expression(funktion,knot->sub[0],strtemp); strtemp=stringlist_einfuegen(strtemp," & "); strtemp=synthesize_expression(funktion,knot->sub[1],strtemp); strtemp=stringlist_einfuegen(strtemp,")"); break; } case 179 : // expr XOR expr { strtemp=stringlist_einfuegen(strtemp,"("); strtemp=synthesize_expression(funktion,knot->sub[0],strtemp); strtemp=stringlist_einfuegen(strtemp," ^ "); strtemp=synthesize_expression(funktion,knot->sub[1],strtemp); strtemp=stringlist_einfuegen(strtemp,")"); break; } case 210 : // not expr { strtemp=stringlist_einfuegen(strtemp,"("); strtemp=stringlist_einfuegen(strtemp," ~ "); strtemp=synthesize_expression(funktion,knot->sub[0],strtemp); strtemp=stringlist_einfuegen(strtemp,")"); break; } case 163 : // leerer Klammerausdruck { break; } case 164 : // expr -> ( expr_list ) { if (knot->sub[0]->subtyp==246) { strtemp=stringlist_einfuegen(strtemp,"("); strtemp=synthesize_expression(funktion,knot->sub[0]->sub[0],strtemp); strtemp=stringlist_einfuegen(strtemp,")"); } else { strtemp=stringlist_einfuegen(strtemp,"!!! '(' expr_list ')'not supported !!!"); } break; } case 182 : // expr -> expr ^ expr d.h. Bits aus Bitvector ausschneiden { /* wenn man an dieser Stelle auf diesen Subtyp trifft, muss die erste expr ein Bitvector sein, denn wenn es eine Zahl waere (d.h. dann wuerde ^ Potenzieren bedeuten), dann waere expr ^ expr schon vorher durch vereinfache_expression ausgewertet worden. Jedenfalls dann, falls die zweite Expression eine Konstante ist, falls nicht, waere in der PVS-Datei ein Fehler, denn Potenzen von Zahlen muessen waehrend des Synthetisierens auswertbar sein (Verilog kann mit Zahlen nix anfangen) */ if (is_constant(knot->sub[1])) // Fall : expr ^ 2 : d.h. zweites Bit des Bitvectors { bearbeitet=1; strtemp=synthesize_expression(funktion,knot->sub[0],strtemp); strtemp=stringlist_einfuegen(strtemp,"["); strtemp=synthesize_expression(funktion,knot->sub[1],strtemp); strtemp=stringlist_einfuegen(strtemp,"]"); } if (knot->sub[1]->subtyp==164) // Fall : expr ^ (5,3) : d.h. mehrere Bits ausschneiden ( expr -> '(' expr_list ')' ) { if ((knot->sub[1]->sub[0]->subtyp==247) // expr_list -> expr ',' expr_list && (is_constant(knot->sub[1]->sub[0]->sub[0])) && (knot->sub[1]->sub[0]->sub[1]->subtyp==246) // expr_list -> expr && (is_constant(knot->sub[1]->sub[0]->sub[1]->sub[0]))) { bearbeitet=1; strtemp=synthesize_expression(funktion,knot->sub[0],strtemp); strtemp=stringlist_einfuegen(strtemp,"["); strtemp=synthesize_expression(funktion,knot->sub[1]->sub[0]->sub[0],strtemp); strtemp=stringlist_einfuegen(strtemp,":"); strtemp=synthesize_expression(funktion,knot->sub[1]->sub[0]->sub[1]->sub[0],strtemp); strtemp=stringlist_einfuegen(strtemp,"]"); } } if (bearbeitet==0) { strtemp=stringlist_einfuegen(strtemp,"!!! Unknown Expression !!!"); } break; } case 168 : // expr -> expr O_OPERATOR expr { // wird synthetisiert zu "{expr,expr}" strtemp=stringlist_einfuegen(strtemp,"{"); strtemp=synthesize_expression(funktion,knot->sub[0],strtemp); strtemp=stringlist_einfuegen(strtemp,","); strtemp=synthesize_expression(funktion,knot->sub[1],strtemp); strtemp=stringlist_einfuegen(strtemp,"}"); break; } case 218 : // expr -> IF expr THEN expr ELSE expr ENDIF { strtemp=stringlist_einfuegen(strtemp,"("); strtemp=synthesize_if218(funktion,knot,strtemp); strtemp=stringlist_einfuegen(strtemp,")"); break; } case 219 : // expr -> IF expr THEN expr elseif_plus ELSE expr ENDIF { strtemp=stringlist_einfuegen(strtemp,"("); strtemp=synthesize_if219(funktion,knot,strtemp); strtemp=stringlist_einfuegen(strtemp,")"); break; } case 196 : // expr -> expr '=' expr { strtemp=stringlist_einfuegen(strtemp,"("); strtemp=synthesize_expression(funktion,knot->sub[0],strtemp); strtemp=stringlist_einfuegen(strtemp,"=="); strtemp=synthesize_expression(funktion,knot->sub[1],strtemp); strtemp=stringlist_einfuegen(strtemp,")"); break; } case 227 : // expr -> LET bind_list IN expr { // die notwendigen Aenderungen am Syntaxbaum durchfuehren und evtl. neue Wire-Defs. einfuegen verarbeite_bindlist(funktion,knot->sub[0],knot->sub[1]); // den geaenderten Syntaxbaum synthetisieren strtemp=synthesize_expression(funktion,knot->sub[1],strtemp); break; } default : { strtemp=stringlist_einfuegen(strtemp,"!!! Unknown Expression !!!"); } } return strtemp; } // übersetzt den Funktionsrumpf einer Funktion struct stringlisten_eintrag *synthesize_functionbody(struct funktionslisten_eintrag *funktion) { struct knoten *temp=funktion->wurzelknoten; struct stringlisten_eintrag *strtemp; // "normale" Funktion if ((temp->sub[2]->subtyp==103) // theory_decl -> const_decl && (temp->sub[2]->sub[0]->subtyp==123)) // const_decl -> type_expr const_value { // dieser Knoten enthält die expression in const_value strtemp=synthesize_expression(funktion,temp->sub[2]->sub[0]->sub[1]->sub[0],hdl_code_zuweisungen); } // rekursive Funktion if ((temp->sub[2]->subtyp==104) // theory_decl -> def_decl && (temp->sub[2]->sub[0]->subtyp==125)) // def_decl -> RECURSIVE type_expr '=' expr MEASURE expr { strtemp=synthesize_expression(funktion,temp->sub[2]->sub[0]->sub[1],hdl_code_zuweisungen); } return strtemp; } // gibt die Parameter-Deklaration einer Funktion in Verilog aus void synthesize_parameter(struct funktionslisten_eintrag *funktion) { int i; int parameter_vorhanden=0; char chartemp[100]; struct stringlisten_eintrag *positionmerke; // Parameterangabe hinter dem Funktionsnamen // Rueckgabeparameter positionmerke=stringlist_append(hdl_code,"(zzz_out")->previous; // positionsmerke zeigt ans Ende des Modulnamens // Eingabeparameter for (i=0;iparameteranzahl;i++) { if (parameter_verbose) { printf("Parameter : %s\t",funktion->parameter[i].name); printf("Typ : "); } if (funktion->parameter[i].is_constant) { // konstante Parameter werden in den Funktionsnamen integriert sprintf(chartemp,"_%d",funktion->parameter[i].wert); positionmerke=stringlist_einfuegen(positionmerke,chartemp); } else { // richtige Parameter werden mitgegeben switch (funktion->parameter[i].typ) { case -1 : { if (parameter_verbose) { printf("Ungültiger Typ\n"); } break; } case -2 : { if (parameter_verbose) { printf("Typ durch get_parametertyp_from_variable nicht festgestellt.\n"); } break; } case bitvector : { if (parameter_verbose) { printf("Bitvector\tBreite : %d\n",funktion->parameter[i].bitvectorbreite); } stringlist_append(hdl_code,","); stringlist_append(hdl_code,funktion->parameter[i].name); // parametername ausgeben break; } case nat : { if (parameter_verbose) { printf("Nat\n"); } break; } case other : { if (parameter_verbose) { printf("Other\n"); } break; } } } } stringlist_append(hdl_code,");\n"); // Deklaration der Parameter (Input,Output,Bitbreite) // Output-Parameter if (funktion->rueckgabe_parameter_typ==bitvector) { stringlist_append(hdl_code,"\toutput "); if (funktion->rueckgabe_parameter_bitvectorbreite>1) { sprintf(chartemp,"[%d:0] ",funktion->rueckgabe_parameter_bitvectorbreite); stringlist_append(hdl_code,chartemp); } stringlist_append(hdl_code,"zzz_out;\n"); } // Input-Parameter for (i=0;iparameteranzahl;i++) { if (funktion->parameter[i].typ==bitvector) { stringlist_append(hdl_code,"\tinput "); if (funktion->parameter[i].bitvectorbreite>1) { sprintf(chartemp,"[%d:0] ",funktion->parameter[i].bitvectorbreite-1); stringlist_append(hdl_code,chartemp); } stringlist_append(hdl_code,funktion->parameter[i].name); stringlist_append(hdl_code,";\n"); } } hdl_code_deklarationen=stringlist_append(hdl_code,"\n"); } // uebersetzt eine einzelne Funktion void synthesize_function(struct funktionslisten_eintrag *funktion) { struct parameterlisten_eintrag *parameter; int i; struct parameterlisten_eintrag *temp; struct funktionslisten_eintrag *temp2=synthetisierte_funktionen; int merke; struct parameter_typ *parameterkopie; // bei Verilog sind Variablen nur innerhalb von Modulen def. => bind_zaehler kann zur besseren Uebersicht wieder auf 0 gesetzt werden bind_zaehler=0; if (synthetisierbar(funktion)==1) { // Nachschauen, ob diese Funktion schon synthetisiert wurde while (temp2) { merke=1; if (strcmp(funktion->funktionsname,temp2->funktionsname)!=0) // Funktionsname ungleich { merke=0; } if (funktion->parameteranzahl!=temp2->parameteranzahl) { merke=0; } else { for (i=0;iparameteranzahl;i++) { if ((funktion->parameter[i].is_constant==temp2->parameter[i].is_constant) && (funktion->parameter[i].is_constant)) { // konstante Parameter muessen uebereinstimmen sonst nicht die gleiche Funktion if (funktion->parameter[i].wert!=temp2->parameter[i].wert) { merke=0; } } } } if (merke==1) { return; // Funktion wurde schon synthetisiert } temp2=temp2->next_function; } // Funktion der Liste mit den schon synthetisierten Funktionen hinzufuegen parameterkopie=(struct parameter_typ *) malloc(funktion->parameteranzahl*sizeof(struct parameter_typ)); allokierter_speicher+=funktion->parameteranzahl*sizeof(struct parameter_typ); for (i=0;iparameteranzahl;i++) { parameterkopie[i].typ=funktion->parameter[i].typ; parameterkopie[i].bitvectorbreite=funktion->parameter[i].bitvectorbreite; parameterkopie[i].is_constant=funktion->parameter[i].is_constant; parameterkopie[i].wert=funktion->parameter[i].wert; if (funktion->parameter[i].name) { parameterkopie[i].name=alloc_str(strlen(funktion->parameter[i].name)); strcpy(parameterkopie[i].name,funktion->parameter[i].name); } else { parameterkopie[i].name=NULL; } } funktionsliste_add(&synthetisierte_funktionen,funktion->funktionsname,NULL,NULL,funktion->parameteranzahl,parameterkopie); // Funktion synthetisieren hdl_code=newstringlist("module "); stringlist_append(hdl_code,funktion->funktionsname); if (parameter_verbose) { varliste_ausgeben(funktion->var_list); } // Code für Parameter-Deklaration erzeugen synthesize_parameter(funktion); // Funktionsrumpf übersetzen hdl_code_zuweisungen=stringlist_append(hdl_code,"\n\tassign zzz_out = "); temp=synthesize_functionbody(funktion); stringlist_einfuegen(temp,";\n"); stringlist_append(hdl_code,"\nendmodule\n\n"); // Speicher fuer Ausgabeliste wieder freigeben stringlist_ausgabe(hdl_code); stringlist_freigeben(hdl_code); } else { if (parameter_verbose) { printf("Funktion %s an dieser Stelle nicht synthetisierbar.\n",funktion->funktionsname); } } } // diese Funktion bestimmt bei einer Funktion die Bitbreiten der Bitvector Parameter void bestimme_bitbreiten(struct funktionslisten_eintrag *funktion) { struct knoten *temp=funktion->wurzelknoten; struct parameter_typ merke; int parameteranzahl; struct parameterlisten_eintrag *tempeintrag; int i; // erst der Rueckgabeparameter // "normale" Funktion if ((temp->sub[2]->subtyp==103) // theory_decl -> const_decl && (temp->sub[2]->sub[0]->subtyp==123)) // const_decl -> type_expr const_value { merke=bestimme_parametertyp(temp->sub[2]->sub[0]->sub[0]); } // rekursive Funktion if ((temp->sub[2]->subtyp==104) // theory_decl -> def_decl && (temp->sub[2]->sub[0]->subtyp==125)) // def_decl -> RECURSIVE type_expr '=' expr MEASURE expr { merke=bestimme_parametertyp(temp->sub[2]->sub[0]->sub[0]); } funktion->rueckgabe_parameter_bitvectorbreite=merke.bitvectorbreite; // dann die anderen Parameter // Parameter aus dem Syntaxbaum raussuchen parameteranzahl=extrahiere_parameter(funktion); if (parameteranzahl!=funktion->parameteranzahl) { printf ("Schwerwiegender Fehler in Funktion bestimme_bitbreiten\n"); exit (1); } // und die Bitbreiten in das Parameterarray uebernehmen tempeintrag=parameterliste; for (i=0;iparameter[i].bitvectorbreite=tempeintrag->bitvector_breite; tempeintrag=tempeintrag->next_parameter; } // Parameterliste für den nächsten Schleifendurchlauf wieder freigeben parameterliste_speicherfreigeben(); } /* diese Funktion vervollstaendigt die unvollstaendigen Angaben in der Funktion gesuchte_funktion (z.B. stehen dort noch keine Parametertypen und Namen) , indem die Funktion in der Funktionsliste gesucht wird (anhand des Namens) und dann die dortigen Daten uebernommen werden Ausserdem erstellt sie eine Kopie des Syntaxbaumes der aufgerufenen Function und ersetzt dort alle bekannten Konstanten durch ihren Wert. Diese Kopie ist dann der Wurzelknoten der Funktion */ void searchandsynthesize_function(struct funktionslisten_eintrag *funktionsliste,struct funktionslisten_eintrag *gesuchte_funktion) { struct funktionslisten_eintrag *temp=funktionsliste; struct funktionslisten_eintrag *temp2=synthetisierte_funktionen; int i,j; struct konstante *konstantenarray; int konstantenanzahl; while ((temp) && (strcmp(temp->funktionsname,gesuchte_funktion->funktionsname)!=0)) { temp=temp->next_function; } if (temp) { // falls Ungereimtheiten ==> abbrechen if (gesuchte_funktion->parameteranzahl!=temp->parameteranzahl) { printf ("Funktion %s wurde mit falsche Parameteranzahl aufgerufen.\n",gesuchte_funktion->funktionsname); exit (1); } // zuerst die Parameternamen und Typen uebernehmen ( wert und is_constant sind schon richtig gesetzt !) // und dabei gleichzeitig die Anzahl der Konstanten bestimmen konstantenanzahl=0; for (i=0;iparameteranzahl;i++) { if (gesuchte_funktion->parameter[i].is_constant) { konstantenanzahl++; } gesuchte_funktion->parameter[i].typ=temp->parameter[i].typ; gesuchte_funktion->parameter[i].bitvectorbreite=temp->parameter[i].bitvectorbreite; if (gesuchte_funktion->parameter[i].name) { freigegebener_speicher+=strlen(gesuchte_funktion->parameter[i].name)+1; free(gesuchte_funktion->parameter[i].name); } gesuchte_funktion->parameter[i].name=alloc_str(strlen(temp->parameter[i].name)); strcpy(gesuchte_funktion->parameter[i].name,temp->parameter[i].name); } // auch den Rueckgabetyp... uebernehmen gesuchte_funktion->rueckgabe_parameter_typ=temp->rueckgabe_parameter_typ; // nun eine Kopie des Syntaxbaums der Originalfunktion erstellen und diese als Wurzelknoten festlegen gesuchte_funktion->wurzelknoten=copysyntaxbaum(temp->wurzelknoten); // die Konstanten in einem Array speichern und dann in der Funktion ersetzen konstantenarray=(struct konstante *) malloc(konstantenanzahl*sizeof(struct konstante)); allokierter_speicher+=konstantenanzahl*sizeof(struct konstante); j=0; for (i=0;iparameteranzahl;i++) { if (gesuchte_funktion->parameter[i].is_constant) { if (gesuchte_funktion->parameter[i].name) { konstantenarray[j].name=alloc_str(strlen(gesuchte_funktion->parameter[i].name)); strcpy(konstantenarray[j].name,gesuchte_funktion->parameter[i].name); } else { konstantenarray[j].name=NULL; } konstantenarray[j].wert=gesuchte_funktion->parameter[i].wert; j++; } } // konstante Variablen durch Konstanten ersetzen ersetze_konstanten(gesuchte_funktion->wurzelknoten,konstantenanzahl,konstantenarray); // Expressions vereinfachen gesuchte_funktion->wurzelknoten=vereinfache_teilbaum(gesuchte_funktion->wurzelknoten); // Bitbreite der Bitvector-Parameter bestimmen bestimme_bitbreiten(gesuchte_funktion); // Speicher fuer Konstantenarray wieder freigeben for (i=0;iwurzelknoten); } else { printf ("Funktion %s wurde aufgerufen, aber nicht deklariert.\n",gesuchte_funktion->funktionsname); exit (1); } } // konvertiert den Parse-Tree nach hdl void synthesize(struct knoten *wurzelknoten) { struct funktionslisten_eintrag *akt_funktion; int parameter_anzahl; int i; struct parameterlisten_eintrag *temp; // den Syntaxbaum durchgehen und z.B. Funktionen in die Funktionenliste eintragen convert_knoten(wurzelknoten); // die Paramter der Funktionen bestimmen und auch in die Funktionenliste eintragen akt_funktion=funktionsliste; while (akt_funktion) { bestimme_rueckgabetyp(akt_funktion); // Parameter aus dem Syntaxbaum raussuchen parameter_anzahl=extrahiere_parameter(akt_funktion); // und in das Parameterarray akt_funktion->parameter eintragen akt_funktion->parameteranzahl=parameter_anzahl; akt_funktion->parameter=(struct parameter_typ *) malloc (parameter_anzahl*sizeof(struct parameter_typ)); allokierter_speicher+=parameter_anzahl*sizeof(struct parameter_typ); temp=parameterliste; for (i=0;iparameter[i].typ=temp->parametertyp; akt_funktion->parameter[i].bitvectorbreite=temp->bitvector_breite; akt_funktion->parameter[i].name=alloc_str(strlen(temp->parametername)); strcpy(akt_funktion->parameter[i].name,temp->parametername); akt_funktion->parameter[i].is_constant=0; /* ob ein Parameter konstant ist, laesst sich nur beim Funktionsaufruf feststellen, nicht bei der Definition ==> deshalb hier vorsichtshalber auf false */ temp=temp->next_parameter; } // Parameterliste für den nächsten Schleifendurchlauf wieder freigeben parameterliste_speicherfreigeben(); akt_funktion=akt_funktion->next_function; } // Die Funktionen aus der funktionsliste nach Verilog umwandeln akt_funktion=funktionsliste; while (akt_funktion) { synthesize_function(akt_funktion); akt_funktion=akt_funktion->next_function; } if (parameter_verbose) { funktionsliste_ausgeben(fehlende_funktionen); } // Jetzt so lange die fehlenden Funktionen durchgehen, bis keine neuen mehr dazukommen // Man kann hierbei keine uebersehen, die z.B. waehrend der while-Schleife hinzukommen, da diese // mit funktionliste_add am ENDE der Liste der fehlenden Funktionen eingefuegt werden akt_funktion=fehlende_funktionen; while (akt_funktion) { /* zuerst die unvollstaendigen Angaben in der Liste fehlende_funktionen (z.B. stehen dort noch keine Parametertypen und Namen) vervollständigen, indem die Funktion in der Funktionsliste gesucht wird (anhand des Namens) und dann die dortigen Daten uebernommen werden */ searchandsynthesize_function(funktionsliste,akt_funktion); akt_funktion=akt_funktion->next_function; } if (parameter_verbose) { funktionsliste_ausgeben(fehlende_funktionen); } funktionsliste=funktionsliste_speicherfreigeben(funktionsliste); fehlende_funktionen=funktionsliste_speicherfreigeben(fehlende_funktionen); synthetisierte_funktionen=funktionsliste_speicherfreigeben(synthetisierte_funktionen); }