Forth и другие саморасширяющиеся системы программирования Locations of visitors to this page
Текущее время: Пт авг 07, 2026 16:08

...
Google Search
Forth-FAQ Spy Grafic

Часовой пояс: UTC + 3 часа [ Летнее время ]




Начать новую тему Ответить на тему  [ Сообщений: 12 ] 
Автор Сообщение
 Заголовок сообщения: распознавалка чисел в формате языка verilog
СообщениеДобавлено: Сб июл 09, 2022 01:19 
Не в сети
Moderator
Moderator
Аватара пользователя

Зарегистрирован: Чт май 04, 2006 00:53
Сообщения: 5063
Откуда: был Крым, теперь Новосибирск
Благодарил (а): 23 раз.
Поблагодарили: 63 раз.
source file: verilog.fts
\ 02.06.2022 ~mOleg
\ Copyright [C] 2022 mOleg mOlegg@ya.ru
\ преобразование строкового представления чисел вида 3'b00101 или 10'h1AF или 7'd23 или '123

branch/ case.fts
math/ double.fts

\ разделить строку по указанному символу char
\ возвращается остаток строки asch и его длина #, начало и длина строки до разделителя
\ если разделитель не встретился, длина #h будет равна 0
: split ( asc # char --> asch #h ascl #l )
>L DDUP BOUNDS
BEGIN DDUP > WHILE
DUP C@ L@ = WHILENOT
C+
REPEAT
THEN
TUCK - DUP >L DSWAP L> -
LDROP ;

\ поиск определенного через `define имени
: Defined ( asc # --> ud asc # )
[CHAR] ' split SFIND \ искать необходимо либо не в словаре VERILOG, либо только по цепочке слов !! иначе будет рекурсия
IF EXECUTE DROP DSWAP
ELSE >STDERR ERROR" - invalid name"
THEN ;

\ определить битовую длину числа
: ?Long ( asc # --> ud asc # )
OVER C@ DUP [CHAR] ` = IF DROP Defined ;THEN
0x0A DIGIT IFNOT 0:0 DSWAP ;THEN DROP \ если битовая длина числа не задана
0:0 DSWAP 0x0A >number
DOVER 0:0 D= ABORT" Can't be zero lenght number!" ;

\ распознать число asc #, как число в системе счисления base
: ?Numb ( asc # base --> ud )
>L 0:0 DSWAP L> >number ABORT" Invalid verilog number" DROP ;

\ выбрать систему счисления для преобразования значения числа
: SelBASE ( asc # --> asc # base )
OVER C@ CASE [CHAR] b OF SKIP1 2 ENDOF
[CHAR] d OF SKIP1 0x0A ENDOF
[CHAR] h OF SKIP1 0x10 ENDOF
DROP 0x0A \ когда система счисления явно не задана используется десятичная
ENDCASE ;

\ определить систему счисления
: ?Base ( asc # --> asc # base )
OVER C@ [CHAR] ' =
IF SKIP1 SelBASE ;THEN
ERROR" Invalid verilog number!" ;

\ по номеру бита # получить установленный бит в указанной позиции числа ud
: DBIT ( # --> ud ) 32 OVER > IF BIT 0 ELSE 32 - BIT 0 SWAP THEN ;

\ маска ud для указанного младших бит № числа ud
: DMASK ( # --> ud ) DBIT 0:1 D- ;

\ инвертировать число двойной длины d
: DINVERT ( d --> ~d ) INVERT SWAP INVERT SWAP ;

\ логарифм по основанию 2 для чисел двойной длины
: DLG2 ( d --> u )
-IF DABS 1 \ д.б. на один бит длиннее, т.к. надо где-то хранить знаковый бит
ELSE 0 THEN
>L BEGIN DDUP OR WHILE \ медленно, но заморачиваться не хочется
D2/ 1 L+
REPEAT DDROP
L> ;

\ определить количество действительных бит # в числе двойной длины d
: DBITS ( d --> # )
0x80000000:0 DOVER D= IF DDROP 64 ;THEN \ DNEGATE не работает нормально, если выставлен только старший бит числа!
DLG2 ;

\ определить действительное количество бит числа двойной длины
: countDBits ( ud# ud --> ud# ud )
DOVER OR ?EXIT
DNIP DDUP DBITS S>D DSWAP ;

\ проверка, влазит ли число ud в указанное количество бит ud#,
\ лишние старшие значащие биты обрезаются
: CheckLong ( ud# ud --> ud# ud )
DOVER D>S DMASK DOVER DOVER DINVERT DAND OR
IF STRING" warning: high bit's of verilog number truncated!" >STDERR THEN
DAND ;

\ преобразовать строку asc # в записи VERILOG в значение числа ud и битовую длину числа ud#
: PosNumber ( asc # --> ud# ud ) ?Long ?Base ?Numb countDBits CheckLong ;

\ преобразовать число asc # , записанное в виде -ux'uy
:> 'VerilogNumber ( asc # --> ud # )
?SIGN IF PosNumber DNEGATE
ELSE PosNumber
THEN DSWAP D>S ;

ALSO HIDDEN

\ ячейка для хранения последнего распознанного VERILOG числа
USER-CREATE last-ver-number 3 CELLS USER-ALLOT

\ извлечь verilog число из addr
: V@ ( addr --> d # ) DUP D@ ROT 2 CELLS + @ ;

\ сохранить verilog число в addr
: V! ( d # addr --> ) TUCK 2 CELLS + ! D! ;

\ компилировать литерал verilog числа d #
: VLIT, ( d # --> )
COMPILE (BOX)
HERE A>L 0 ,
>L D, L> ,
HERE AL@ - AL> !
COMPILE V@ ;

\ литерал для verilog чисел d #
: Vliteral ( d # --> ) state IF VLIT, THEN ;

\ метод работы с verilog числами для словаря
: (VerLit) ( --> d # ) last-ver-number V@ Vliteral ; IMMEDIATE


\ попытка распознать число, заданное строкой: asc #
\ как verilog число
:> 'sVerLfa ( asc # vid --> lfa | 0 )
DROP \ vid словаря не нужен
'VerilogNumber CATCH IF DDROP 0 ;THEN
last-ver-number V! LFA (VerLit) ;

ALSO HIDDEN

init: VOCABULARY \ создание словаря
VOC-LIST A@ >L \ wordlist
'sVerLfa L@ off_quest A!
['] (mount) L@ off_mount A!
['] no-umount L@ off_umount A!
&vinit L> off_vflags B!
;stop VERILOG
PREVIOUS
PREVIOUS

\ преобразовать указанное количество цифр числа ud
: ##S ( ud # --> ud ) BEGIN DUP WHILE >L # L> 1 - REPEAT DROP ;

\ отобразить верилог число d # в текущей системе счисления
: .vn ( d # --> )
OVER >L DUP >L S>D DSWAP DABS
<# BASE@ CASE 2 OF L> ##S DDROP [CHAR] b ENDOF
10 OF LDROP #S DDROP [CHAR] d ENDOF \ количество цифр считать влом!
16 OF L> 4 /MOD SWAP IF 1 + THEN ##S DDROP [CHAR] h ENDOF
ERROR" undefined base for verilog number!"
ENDCASE HOLD [CHAR] ' HOLD
0x0A TO BASE@ #S
L> SIGN
#> TYPE ;

\ отобразить verilog число d # в шестнадцатиричной системе счисления
: .vh ( d # --> )
OVER >L DUP >L S>D DSWAP DABS
0x10 {# L> 4 /MOD SWAP IF 1 + THEN ##S DDROP s" 'h" HOLDS
0x0A TO BASE@ #S
L> SIGN
#> TYPE ;

\ отобразить verilog число d # в десятичной системе счисления
: .vd ( d # --> )
OVER >L S>D DSWAP DABS
0x0A {# #S DDROP
s" 'd" HOLDS #S
L> SIGN
#> TYPE ;

\ отобразить verilog число d # в двоичной системе счисления
: .vb ( d # --> )
OVER >L DUP >L S>D DSWAP DABS
0x02 {# L> ##S DDROP s" 'b" HOLDS
0x0A TO BASE@ #S
L> SIGN
#> TYPE ;

ALSO VERILOG UNDER


Ну, и примеры использования (просто набираем в консоли):
'123 .vn
'd123 .vn
'h1A3E .vn
10'd333 .vn
-12'b11100101010111 .vn
и т.д.

_________________
Мне бы только мой крошечный вклад внести,
За короткую жизнь сплести
Хотя бы ниточку шёлка.
fleur


Вернуться к началу