Forth http://fforum.winglion.ru/ |
|
И снова - 16 Minimal instructions. http://fforum.winglion.ru/viewtopic.php?f=3&t=2564 |
Страница 3 из 3 |
Автор: | Hishnik [ Сб апр 10, 2010 13:37 ] |
Заголовок сообщения: | |
mOleg писал(а): всеравно картина по частоте использования есть.
видно, что чаще всего литералы встречаются, потом DUP DROP SWAP @ + OVER ! и удивительно часто NOOP PC и embedded программы достаточно существенно отличаются. Для embedded характерен больший удельный вес операций работы с памятью и портами, потому что монитор и файловая система как-то нечасто встречаются в таких системах. И если для PC нет-нет да и проскакивает DUP . , то для embedded такая отладочная печать может быть либо невозможна (по причине отсутствия устройства, поддерживающего символьный вывод), либо малоосмысленна (экран 16x2, который мгновенно забьется этой отладочной печатью). |
Автор: | Hishnik [ Сб апр 10, 2010 13:40 ] |
Заголовок сообщения: | |
вопрос писал(а): это плохо для призводительности, если не сделать какую-либо более хитрую оптимизацию
А какую же оптимизацию тут еще можно сделать, если объем операций может быть обусловлен требованиями ТЗ? Если надо посчитать c = a + b, то это будет a @ + b @ + c !. При этом a b c представляют собой литералы - адреса переменных. |
Автор: | mOleg [ Сб апр 10, 2010 13:55 ] |
Заголовок сообщения: | |
Хищник писал(а): PC и embedded программы достаточно существенно отличаются
я это понимаю, поэтому и спрашивал статистику посмотреть, на которую ссылался Хищник Более того, то, что у меня есть собиралось совсем для другой вещи - я смотрел наименее редко используемые операции, чтобы потом по возможности вынести их из ядра во внешние библиотеки. |
Автор: | вопрос [ Сб апр 10, 2010 14:02 ] |
Заголовок сообщения: | |
наименее редко используемые операции, чтобы потом по возможности вынести == наиболее часто вынести |
Автор: | WingLion [ Сб апр 10, 2010 15:20 ] |
Заголовок сообщения: | |
вопрос писал(а): это плохо для призводительности, если не сделать какую-либо более хитрую оптимизацию
Интересное это дело! - Оптимизировать шкуру неубитого медведя!.. |
Автор: | Hishnik [ Вс апр 11, 2010 16:52 ] |
Заголовок сообщения: | |
А что с командным конвейером? Какая ширина команд? Я тут уже готов на VHDL прикинуть. |
Автор: | WingLion [ Вс апр 11, 2010 17:49 ] |
Заголовок сообщения: | |
Прикидка на VHDL, которая у меня получилась: Код: -- version of 12 april 2010
LIBRARY IEEE; USE IEEE.std_logic_1164.all; USE IEEE.std_logic_unsigned.all; --Minimal instruction Forth Computer -- --MIFC16 -- --0 NOP выборка следующей команды (нет операции) --1 ?BRANCH (IFNZ) переход, если на стеке не ноль --2 LIT загрузка непосредственного литерала на стек ( --> data ) --3 @ извлечь данное по адресу из стека ( addr --> data=mem[addr]) --4 ! сохранить даное в памяти по адресу ( data, addr --> ) --5 CALL вызов попрограммы ( вызов адресного интерпретатора) --6 RET возврат из подпрограммы --7 DUP дублирование данного с вершины стека ( d --> d d) --8 DROP удаление данного с вершины стека ( d --> ) --9 SWAP перестановка двух элементов на вершине стека ( d1 d2 --> d2 d1) --10 OVER копирование второго элемента стека ( d1 d2 --> d2 d1 d2) --11 AR> переместить данное со стека данных на стек возвратов ( adr --> ) --12 A>R переместить данное со стека возвратов на стек данных ( --> adr) --13 NAND поразрядное логическое "И-НЕ" двух верхних элементов стека ( d1 d1 --> d1 nand d2) --: NOT DUP NAND ; поразрядное логическое инвертирование верхнего элемента стека (d --> not d) --: OR NOT SWAP NOT NAND ; поразрядное логическое "ИЛИ" двух верхних элементов стека ( d1 d1 --> d1 or d2 ) --: AND NAND DUP NAND ; поразрядное логическое "И" ( d1 d1 --> d1 and d2 ) --: XOR OVER OVER NAND DUP >R NAND SWAP R> NAND NAND ; поразрядное "Исключающее ИЛИ" ( d1 d1 --> d1 xor d2) --14 ADD сложить два верхних элемента стека (d1 d1 --> d1+d2) --15 2/ разделить верхний элемент стека на 2 ( d --> d/2) --: 2* DUP ADD ; entity mifc16 is GENERIC ( widtX : integer :=16 ); Port( clk : in std_logic; ready : in std_logic := '1'; reset : in std_logic := '1'; di : in std_logic_vector (WidtX-1 downto 0); adr : out std_logic_vector (WidtX-1 downto 0); do : out std_logic_vector (WidtX-1 downto 0); test_Cmd : out std_logic_vector (3 downto 0); test_Trigg : out std_logic; test_DStDo : out std_logic_vector (WidtX-1 downto 0); test_RStDo : out std_logic_vector (WidtX-1 downto 0); cs_RAM,wr_RAM,rd_RAM,Out_ena : out std_logic ); END mifc16; ARCHITECTURE RTL OF mifc16 IS type wait_mashine is (Work1, Wait1, Wait2); subtype T_data is std_logic_vector (WidtX-1 downto 0); signal RStcmd : std_logic_vector (1 downto 0); signal RStDi : T_data; -- std_logic_vector (WidtX-1 downto 0); signal RStDo : T_data; -- std_logic_vector (WidtX-1 downto 0); signal DStcmd : std_logic_vector (1 downto 0); signal DStDi : T_data; -- std_logic_vector (WidtX-1 downto 0); signal DStDo : T_data; -- std_logic_vector (WidtX-1 downto 0); constant STnop : std_logic_vector (1 downto 0) := "00"; constant STpush : std_logic_vector (1 downto 0) := "01"; constant STpop : std_logic_vector (1 downto 0) := "10"; constant STswap : std_logic_vector (1 downto 0) := "11"; signal STM : wait_mashine; signal ENA : std_logic; signal stw : std_logic_vector (3 downto 0); signal rst1 : std_logic; signal cmdS : std_logic_vector (3 downto 0); signal cmdr : T_data; signal NEWcmdr : T_data; signal zero : T_data; signal CMD4shr : T_data; signal WrRAM : std_logic; signal RdRAM : std_logic; signal CsRAM : std_logic; signal PC : T_data; -- std_logic_vector (WidtX-1 downto 0); signal newPC : T_data; -- std_logic_vector (WidtX-1 downto 0); signal TR : T_data; -- std_logic_vector (WidtX-1 downto 0); signal newTR : T_data; -- std_logic_vector (WidtX-1 downto 0); signal alux : T_data; -- std_logic_vector (WidtX-1 downto 0); signal mul_res : std_logic_vector (WidtX+WidtX-1 downto 0); signal Trigg,NewTrigg : std_logic; -- внутренний WAIT - '0' - команда исполняется за один такт, иначе - не меньше 3-х signal IntWait : std_logic; COMPONENT Stack IS GENERIC ( WidtX : integer :=16; depth : integer :=3); Port ( clk : in std_logic; cmd : in std_logic_vector (1 downto 0); di : in std_logic_vector (widtX-1 downto 0); do : out std_logic_vector (widtX-1 downto 0); ena : in std_logic ); END COMPONENT; BEGIN stack_dd: stack GENERIC MAP ( widtX => WidtX, depth => 8 ) PORT MAP (clk,DSTcmd,DSTdo,DSTdi,ENA); stack_rr: stack GENERIC MAP ( widtX => WidtX, depth => 8 ) PORT MAP (clk,RSTcmd,RSTdo,RSTdi,ENA); zero <= (others => '0'); -- command register 4-bit shifted CMD4shr(widtX-5 downto 0) <= (cmdr(widtX-1 downto 4)); CMD4shr(widtX-1 downto widtX-4)<=zero(widtX-1 downto widtX-4); -- REGISTERS and RESET SHEME process (clk,ena) begin if (CLK'event and CLK='1' and ENA='1' ) then if rst1 = '0' then cmdr <= zero; PC <= zero; TR <= newTR; Trigg <= '0'; else cmdr <= NEWcmdr; PC <= newPC; TR <= newTR; Trigg <= NewTrigg; end if; end if; end process; -- !!! WAIT MACHINE !!! process (clk,STM) begin if (CLK'event and CLK='1' ) then if reset = '0' then STM <= Work1; ENA <= '1'; stw <= (others => '0'); rst1 <= '0'; else rst1 <= '1'; case STM is when Work1 => if (IntWait = '1') then STM <= Wait1; ENA <= '0'; stw <= zero (3 downto 0) + 1; else STM <= Work1; ENA <= '1'; stw <= zero (3 downto 0); end if; when Wait1 => if (stw = 1) then stw <= zero (3 downto 0) + 1; else stw <= stw - 1; end if; ENA <= '0'; if ((stw = 1) and ready = '1') then STM <= Wait2; else STM <= Wait1; end if; when Wait2 => STM <= Work1; ENA <= '1'; stw <= (others => '0'); end case; end if; end if; end process; CmdS <= cmdr (3 downto 0); -- MAIN COMMAND CASE process (NEWcmdr(3 downto 0)) begin case conv_integer(NEWcmdr(3 downto 0)) is when 0 => IntWait <= '1'; when 1 => IntWait <= '1'; when 2 => IntWait <= '1'; when 5 => IntWait <= '1'; when 3 => intWait <= Trigg; when 4 => intWait <= Trigg; when others => IntWait <= '0'; end case; end process; process (cmdr (3 downto 0)) begin case conv_integer(cmdr (1 downto 0)) is when 1 => alux <= TR nand DSTdi; when 2 => alux <= TR + DSTdi; when 3 => alux <= TR(WidtX-1)&TR(WidtX-1 downto 1); when others => alux <= TR; end case; case conv_integer(cmdr (3 downto 0)) is -- NOP when 0 => NEWcmdr <= di; newPC <= PC + 1; RStcmd <= STnop; NewTrigg <= '0'; RStdo <= RStdi; newTR <= TR; DStcmd <= STnop; DStdo <= DStdi; CsRAM <= '0'; WrRAM <= '1'; RdRAM <= '0'; -- LIT when 1 => NEWcmdr <= cmd4shr; newPC <= PC + 1; RStcmd <= STnop; NewTrigg <= '0'; DStdo <= TR; newTR <= di; DStcmd <= STpush; RStdo <= RStdi; CsRAM <= '0'; WrRAM <= '1'; RdRAM <= '0'; -- CALL when 2 => NEWcmdr <= cmd4shr; NewTrigg <= '0'; newPC <= di; RStDo <= PC + 1; RStcmd <= STpush; newTR <= TR; DStcmd <= STnop; DStdo <= DStdi; CsRAM <= '0'; WrRAM <= '1'; RdRAM <= '0'; -- @ when 3 => newTrigg <= not Trigg; if Trigg = '0' then CsRAM <= '1'; WrRAM <= '1'; RdRAM <= '1'; NEWcmdr <= cmdr; RStcmd <= STpush; newPC <= TR; RStdo <= PC; newTR <= DStdi; DStcmd <= STpop; DStdo <= DStdi; else CsRAM <= '0'; WrRAM <= '1'; RdRAM <= '0'; NEWcmdr <= cmd4shr; RStcmd <= STpop; newPC <= RSTdi; RStdo <= RStdi; newTR <= di; DStcmd <= STpush; DStdo <= TR; end if; -- ! when 4 => newTrigg <= not Trigg; if Trigg = '0' then CsRAM <= '1'; WrRAM <= '1'; RdRAM <= '1'; NEWcmdr <= cmdr; RStcmd <= STpush; newPC <= TR; RStdo <= PC; DStcmd <= STpop; newTR <= DStdi; DStcmd <= STpop; DStdo <= DStdi; else CsRAM <= '0'; WrRAM <= '0'; RdRAM <= '1'; NEWcmdr <= cmd4shr; RStcmd <= STpop; newPC <= RSTdi; RStdo <= RStdi; DStcmd <= STpop; newTR <= DStdi; DStcmd <= STpop; DStdo <= DStdi; end if; -- ?BRANCH when 5 => NEWcmdr <= cmd4shr; RStdo <= RStdi; NewTrigg <= '0'; newTR <= TR; DStcmd <= STnop; DStdo <= DStdi; CsRAM <= '0'; WrRAM <= '1'; RdRAM <= '0'; if (TR = 0) then newPC <= PC + 1; RStcmd <= STnop; else newPC <= di; RStcmd <= STnop; end if; -- RET when 6 => NEWcmdr <= cmd4shr; NewTrigg <= '0'; newPC <= RStDi; RStcmd <= STpop; RStdo <= RStdi; newTR <= TR; DStcmd <= STnop; DStdo <= DStdi; CsRAM <= '1'; WrRAM <= '1'; RdRAM <= '1'; -- DUP when 7 => NEWcmdr <= cmd4shr; RStcmd <= STnop; newPC <= PC; CsRAM <= '1'; WrRAM <= '1'; RdRAM <= '1'; NewTrigg <= '0'; RStdo <= RStdi; newTR <= TR; DStcmd <= STpush; DStdo <= TR; -- DROP when 8 => NEWcmdr <= cmd4shr; RStcmd <= STnop; newPC <= PC; CsRAM <= '1'; WrRAM <= '1'; RdRAM <= '1'; NewTrigg <= '0'; RStdo <= RStdi; newTR <= DSTdi; DStcmd <= STpop; DStdo <= TR; -- SWAP when 9 => NEWcmdr <= cmd4shr; RStcmd <= STnop; newPC <= PC; CsRAM <= '1'; WrRAM <= '1'; RdRAM <= '1'; NewTrigg <= '0'; RStdo <= RStdi; -- swap* newTR <= DSTdi; DStcmd <= STswap; DStdo <= TR; -- OVER when 10 => NEWcmdr <= cmd4shr; RStcmd <= STnop; newPC <= PC; CsRAM <= '1'; WrRAM <= '1'; RdRAM <= '1'; NewTrigg <= '0'; RStdo <= RStdi; -- dup* newTR <= DSTdi; DStcmd <= STpush; DStdo <= TR; -- R> when 11 => NEWcmdr <= cmd4shr; RStcmd <= STpop; newPC <= PC; CsRAM <= '1'; WrRAM <= '1'; RdRAM <= '1'; NewTrigg <= '0'; RStdo <= RStdi; newTR <= RStdi; DStcmd <= STpush; DStdo <= TR; -- >R when 12 => NEWcmdr <= cmd4shr; RStcmd <= STpush; newPC <= PC; CsRAM <= '1'; WrRAM <= '1'; RdRAM <= '1'; NewTrigg <= '0'; RStdo <= TR; newTR <= DStdi; DStcmd <= STpop; DStdo <= DStdi; -- NAND when 13 => CsRAM <= '1'; WrRAM <= '1'; RdRAM <= '1'; NEWcmdr <= cmd4shr; RStcmd <= STnop; newPC <= PC; NewTrigg <= '0'; RStdo <= RStdi; newTR <= alux; -- TR nand DSTdi; DStcmd <= STpush; DStdo <= TR; -- ADD when 14 => CsRAM <= '1'; WrRAM <= '1'; RdRAM <= '1'; NewTrigg <= '0'; NEWcmdr <= cmd4shr; RStcmd <= STnop; newPC <= PC; RStdo <= RStdi; -- dup* newTR <= alux; -- TR + DSTdi; DStcmd <= STpush; DStdo <= TR; -- 2/ when 15 => CsRAM <= '1'; WrRAM <= '1'; RdRAM <= '1'; NewTrigg <= '0'; NEWcmdr <= cmd4shr; RStcmd <= STnop; newPC <= PC; RStdo <= RStdi; newTR <= alux; -- TR(WidtX-1)&TR(WidtX-1 downto 1); DStcmd <= STpush; DStdo <= TR; when others => NEWcmdr <= cmd4shr; RStcmd <= STnop; newPC <= PC; CsRAM <= '1'; WrRAM <= '1'; RdRAM <= '1'; NewTrigg <= '0'; RStdo <= RStdi; DStdo <= DStdi; DStcmd <= STnop; DStdo <= DStdi; newTR <= TR; end case; end process; do <= TR; adr <= PC; test_cmd <= CmdS; Out_ena <= ENA; cs_RAM <= csRAM or ENA; rd_RAM <= rdRAM or ENA; wr_RAM <= wrRAM or ENA; test_Trigg <= Trigg; test_RStDo <= RSTdo; test_DStDo <= DSTdo; END RTL; -- LIBRARY IEEE; USE IEEE.std_logic_1164.all; USE IEEE.std_logic_unsigned.all; ENTITY stack IS GENERIC ( WidtX : integer := 16; depth : integer := 3 ); Port ( clk : in std_logic; cmd : in std_logic_vector (1 downto 0); di : in std_logic_vector (WidtX-1 downto 0); do : out std_logic_vector (WidtX-1 downto 0); ena : in std_logic ); END stack; ARCHITECTURE SRTL OF stack IS attribute altera_attribute : string; attribute altera_attribute of SRTL: architecture is "-name AUTO_SHIFT_REGISTER_RECOGNITION OFF"; TYPE Tstack IS array (depth-1 downto 0) OF std_logic_vector (WidtX-1 downto 0); constant nop : std_logic_vector (1 downto 0) := "00"; constant push : std_logic_vector (1 downto 0) := "01"; constant pop : std_logic_vector (1 downto 0) := "10"; constant swap : std_logic_vector (1 downto 0) := "11"; signal st : Tstack; BEGIN process (clk,cmd) begin if (clk'event and clk='1' and ena = '1') then case cmd is when nop => st <= st; when pop => st(depth-2 downto 0) <= st(depth-1 downto 1); st(depth-1) <= (others => '0'); when push => st(depth-1 downto 1) <= st(depth-2 downto 0); st(0) <= di; when swap => st(depth-1 downto 1) <= st(depth-1 downto 1); st(0) <= di; end case; end if; end process; do <= st(0); END ARCHITECTURE; На CYCLONE-II эта штучка вытягивает до 180MHz При условии, что обращение к внутренней памяти занимает 3 такта - получается 60MIPS |
Автор: | WingLion [ Вс апр 11, 2010 18:28 ] |
Заголовок сообщения: | |
Немного поигрался с компилятором... EP2C20F484C7 -- 16 bit вариант - 180MHz - 710 LCELLs EP2C20F484C7 -- 32 bit вариант - 148MHz - 1383 LCELLs EP2AGX45CU17C4 -- 16 bit вариант - 418MHz - 318 ALUTs EP2AGX45DF25C4 -- 32 bit вариант - 362MHz - 739 ALUTs Добавка через день (компилировано на работе, на лицензионном квартусе) EP3SE50F484C2 - 16 бит - 393ALUTs - 470MHz EP4CGX22CF19C6 - 16 bit - 732LCELLs - 277MHz EP3C16Q240C8 - 16 bit - 730LCELLs - 198MHz |
Автор: | WingLion [ Пн апр 12, 2010 20:51 ] |
Заголовок сообщения: | |
Вчерашний код процессора отредактирован (новая версия - два поста выше). Добавлены: 1. автомат ожидания - вставляет нужное количество тактов в циклы чтения памяти (минимум - два такта). 2. схема быстрого исполнения для команд, не требующих обащения к памяти - исполняются за один такт без тактов ожидания. 3. коды команд приведены в соответствие со списком в начале исходника 4. удалены левые коментарии |
Страница 3 из 3 | Часовой пояс: UTC + 3 часа [ Летнее время ] |
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group http://www.phpbb.com/ |