Mix
Random mix of pages and files
PSI2SI
2026.08.26 03:30:16 end SW Gilhad


PSI2SI - Preprocesor pro WinCUPL

PSI2SI (Preprocessor Simulation Input to Simulation Input) je nástroj v jazyce Python, který řeší chyby a omezení starších verzí simulatoru WinCUPL/Winsim (konkrétně verze 5.30.4 a starší).

Motivace

Starší verze WinCUPL obsahují chybu, kdy použití vlastních maker přímo v souborech .SI způsobí pád aplikace („unhandled exception“). Navíc chybí podpora znaku tečky . pro opakování poslední hodnoty ve vektoru.

Tento preprocesor obchází tyto problémy tak, že vezme vlastní rozšířený soubor .PSI, vyhodnotí všechna makra, provede potřebnou aritmetiku a vygeneruje čistý, zastupitelný soubor .SI, který už WinCUPL bez problémů pochytí.

Instalace a použití

Skript nevyžaduje žádné externí závislosti nad rámec standardní knihovny Pythonu 3.

Základní volání:

python PSI2SI.py vstup.PSI vystup.SI

Pokud při zpracování dojde k chybě (např. chybná syntaxe makra), skript vypíše detaily na standardní chybový výstup (stderr) a pokračuje ve zpracování.

Syntaxe souboru .PSI

Soubor .PSI je směsicí standardního kódu pro WinCUPL a speciálních direktiv preprocesoru. Direktivy začínají znakem # bez mezery.

Komentáře

Staré komentáře

Standardní blokové komentáře WinCUPL jsou podporovány a jsou před zpracováním z textu odstraněny. Preprocesor respektuje uvozovky (znaky " a ' uvnitř komentáře neukončí komentář předčasně).

/* Toto je komentář a bude smazán */
MSG "Toto není komentář /* protoze je to v retezci */";

Nové komentáře (direktivy preprocesoru)

Preprocesor přidává vlastní systém komentářů, který podporuje vnořování a hlavně expanzi proměnných z maker.

  • #comment Text s {promennou} – Vytvoří jednořádkový komentář. Vygeneruje: /* Text s hodnotou */
  • #comm_start Text a #comm_end – Vytvoří víceřádkový blok. Vše mezi těmito direktivy se zkopíruje a expandují se v něm proměnné.
  • #// nebo #none – Jednořádkový "tichý" komentář. Používá se uvnitř maker. Řádek se úplně ignoruje a nic nevygeneruje.
#comm_start Začátek testu registru {reg_name}
Toto je taky součástí komentáře.
#comm_end

Definice maker

Makra se definují pomocí #def_macro (nebo #macro) a končí pomocí #end_macro. Definice maker se nesmí vnořovat, ale uvnitř makra lze volat jiné makro.

#def_macro NAZEV_MAKRA(param1, param2)
    $MSG "Volani makra: {param1}, {param2}";
#end_macro

Předávání parametrů:

  • Hexa symboly: Pokud se parametr přečte jako platné hexadecimální číslo (např. FF, 10, 1A), převede se interně na integer.
  • Řetězce: Pokud je parametr uzavřen v uvozovkách nebo apostrofech (např. "text" nebo 'A0'), zpracuje se jako textový řetězec (s podporou escape sekvencí jako \").

Matematické výrazy (Expanze {...})

Kdekoli v textu (v $MSG, v komentářích i v příkazech #set) lze použít složené závorky {...}. Obsah se vyhodnotí jako matematický výraz.

  • Pokud je výsledkem celé číslo, formátuje se jako velká hexadecimální hodnota (např. 255 -> FF).
  • Lze používat standardní operátory (+, -, *, /).
  • Hexadecimální literály se píší bez prefixu (např. A000). Kalkulačka je inteligentní – pokud slovo neodpovídá názvu parametru makra a obsahuje jen hexa znaky, převede ho na číslo.

Příklad sčítání adres: Pokud voláte makro s parametrem reg_num = 8, zápis {'A000'+reg_num} se vyhodnotí jako 0xA000 + 8 a výsledkem bude řetězec A008.

Pokud výraz obalíte do uvozovek/apostrofů, např. '{A000'+reg_num}', preprocesor tyto obalovací znaky zachová a výsledkem bude 'A008'.

Generování vektorů (Stavový automat)

Preprocesor "sleduje" aktuální stav vektorů. Když WinCUPL vidí řádek s vektorem, preprocesor si zapamatuje hodnoty jednotlivých pinů. To umožňuje generovat nové vektory pomocí #SET a #GEN_VECTOR bez nutnosti opisovat celý řádek.

Konfigurace sběrnic (#FIELD_SIZE)

Definuje šířku sběrnic v bitech. Všechny piny nezmíněné v tomto seznamu mají automaticky šířku 1 bit.

#field_size DATA=8 ADDR=16 COUNT=13

Příkaz ORDER

Preprocesor analyzuje standardní příkaz ORDER. Důležité chování:

  • Formátovací texty obalené do uvozovek (např. " CNT:") se přenesou do výstupu, ale při generování vektorů se zcela ignorují (nezabírají místo v datovém řádku).
  • Znak ! (active low) se respektuje, ale pro logiku preprocesoru se ignoruje.

Příkazy #SET a #GEN_VECTOR

Slouží k měnění stavu a tvorbě vektorových řádků uvnitř maker.

  • #SET SIGNAL = HODNOTA – Připraví změnu pro další generovaný vektor.
  • #GEN_VECTOR – Vygeneruje vektorový řádek. Vezme aktuální paměťovaný stav, přepíše pouze ty sloupce, které byly nastaveny přes #SET, výsledek zapíše do výstupu a paměť aktualizuje. Seznam připravených změn se poté vymaže.

Pravidla pro formátování hodnot v ``#SET``: Chování preprocesoru ohledně uvozovek a apostrofů přesně odpovídá potřebám WinCUPL:

  • Vstupní hodnoty (pro simulátor): Chceme je obalit do apostrofů (např. '80').
  • Výstupní hodnoty (jen pro logování): Chceme je obalit do uvozovek (např. "*").
  • Pokud v #SET hodnotu neobalíte ničím, preprocesor ji automaticky vygeneruje v apostrofech (např. #SET DATA = {value} s hodnotou 80 vygeneruje '80').
  • Pokud hodnotu v #SET obalíte, preprocesor respektuje vámi zvolený obal (např. #SET COUNT = "*"" vygeneruje přesně "*").

Kompletní příklad

MSG "### Start simulace ###";

/* Definice šířek sběrnic */
#field_size DATA=8 ADDR=16

#def_macro WRITE_REG(reg_num, value)
#// Tento řádek se nepřeloží a nevygeneruje
#comm_start Zapisuji data {value} na adresu {'A000'+reg_num}
(Toto je taky součástí komentáře)
#comm_end

$MSG "### WRITE_REG({reg_num}, {value}) ###";

#set ADDR = {'A000'+reg_num}
#set Rw   = 0
#set DATA = {value}

#set E = 0;
#set Q = 1;
#gen_vector

#set E = 1;
#gen_vector

#set Q = 0;
#gen_vector

#set E = 0;
#gen_vector
#end_macro

ORDER: !Dev_FIRQ, %1, !Reset, BA, %1, E, Q, Rw, %1, ADDR, %1, DATA, %1, " CNT:", COUNT ;

VECTORS:

$MSG "## Počáteční stav";
Z 00 C01 'A008' "*" *****

#call WRITE_REG(8, 80)

Výsledný soubor .SI

MSG "### Start simulace ###";

MSG "### WRITE_REG(8, 80) ###";

/* Zapisuji data 80 na adresu A008
(Toto je taky součástí komentáře)
*/
Z 10 010 'A008' '80' *****
Z 10 110 'A008' '80' *****
Z 10 100 'A008' '80' *****
Z 10 000 'A008' '80' *****

ORDER: !Dev_FIRQ, %1, !Reset, BA, %1, E, Q, Rw, %1, ADDR, %1, DATA, %1, " CNT:", COUNT ;

VECTORS:

$MSG "## Počáteční stav";
Z 00 C01 'A008' "*" *****

Licence

Tento skript byl vytvořen pro usnadnění vývoje hardwaru na starších platformách. Můžete jej volně používat a upravovat podle svých potřeb.