aboutsummaryrefslogtreecommitdiffstats
path: root/quantum/process_keycode/process_unicode.c
Commit message (Expand)AuthorAgeFilesLines
* clang-format changesskullY2019-08-301-6/+6
* New keycode macro (XP) for shifted character pairs using UNICODEMAP + bug fix...Konstantin Đorđević2019-05-031-3/+3
* Overhaul Unicode Common functionality (#4325)Drashna Jaelre2018-12-191-2/+0
* Fix Unicode EEPROM handling so it is consistent. (#4066)Drashna Jaelre2018-10-191-6/+1
* Fix undefined eeprom warnings in unicode processingFred Sundvik2017-04-131-0/+1
* Worked around some new Makefile issues.nielsenz2017-03-301-0/+1
* Pulling and pushing troublesnielsenz2017-03-301-75/+0
* Merge branch 'master' into to_pushZay9502017-03-291-179/+17
|\
| * Clarify the quantum license (#1042)skullydazed2017-03-281-0/+15
| * add unicode common file, get names rightJack Humbert2017-02-151-85/+0
| * split up unicode systems into different filesJack Humbert2017-02-151-200/+0
| * Implement tap mod dual role for right side mods.Priyadi Iman Nurcahyo2017-02-101-1/+1
| * Merge pull request #981 from jonasoberschweiber/osx-surrogate-pairsJack Humbert2017-02-061-1/+10
| |\
| | * Add support for supplementary planes for OS XJonas Oberschweiber2016-12-311-1/+10
| * | Unregister all mods before inputting Unicode, and reregister afterwardsPriyadi Iman Nurcahyo2017-01-091-8/+33
| |/
* / Keep unicode's input_mode through a power cycleZach Nielsen2016-11-101-0/+6
|/
* Merge pull request #844 from priyadi/unicode_wincompose_inputJack Humbert2016-10-261-0/+5
|\
| * Unicode WinCompose input methodPriyadi Iman Nurcahyo2016-10-231-0/+5
* | UNICODE_MAP: remove 5 char limit; ignore leading zeroes; handle OS limitationsPriyadi Iman Nurcahyo2016-10-231-7/+27
|/
* Unicode map framework. Allow unicode up to 0xFFFFF using separatePriyadi Iman Nurcahyo2016-10-101-0/+26
* Declare Unicode method hex_to_keycode() as “weak”coderkun2016-10-021-0/+1
* process_unicode: Add get_unicode_input_mode()Gergely Nagy2016-08-311-0/+4
* quantum: Move qk_ucis_state to process_unicode.cGergely Nagy2016-08-241-0/+2
* Drop method to set Unicode input key and declare start and finish methods as ...coderkun2016-08-211-8/+4
* Add method to set Unicode input key for ISO 14755coderkun2016-08-211-2/+8
* process_unicode: Introduce a slight delayGergely Nagy2016-08-151-0/+4
* process_unicode: Replace register_hex32Gergely Nagy2016-08-151-9/+28
* process_unicode: Use uint32_t for UCIS purposesGergely Nagy2016-08-151-3/+9
* process_unicode: Make the startup overridableGergely Nagy2016-08-151-0/+5
* process_unicode: Call process_ucis() automaticallyGergely Nagy2016-08-151-1/+1
* process_unicode: Handle too long UCIS symbol namesGergely Nagy2016-08-151-1/+9
* process_unicode: Add a way to enter unicode symbols by nameGergely Nagy2016-08-151-1/+92
* process_unicode: Small refactor & linux fixGergely Nagy2016-08-151-31/+45
* process_unicode: Fix set_unicode_input_mode()Gergely Nagy2016-08-131-1/+1
* Moves features to their own files (process_*), adds tap dance feature (#460)Jack Humbert2016-06-291-0/+57
485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605
--  Routine to dump (for debugging purpose) a netlist.
--  Copyright (C) 2017 Tristan Gingold
--
--  This file is part of GHDL.
--
--  This program is free software; you can redistribute it and/or modify
--  it under the terms of the GNU General Public License as published by
--  the Free Software Foundation; either version 2 of the License, or
--  (at your option) any later version.
--
--  This program is distributed in the hope that it will be useful,
--  but WITHOUT ANY WARRANTY; without even the implied warranty of
--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
--  GNU General Public License for more details.
--
--  You should have received a copy of the GNU General Public License
--  along with this program; if not, write to the Free Software
--  Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
--  MA 02110-1301, USA.

with Ada.Text_IO; use Ada.Text_IO;
with Name_Table; use Name_Table;
with Netlists.Utils; use Netlists.Utils;
with Netlists.Iterators; use Netlists.Iterators;
with Netlists.Gates; use Netlists.Gates;

package body Netlists.Disp_Vhdl is
   Flag_Merge_Lit : constant Boolean := True;

   --  Like Put, but without the leading space (if any).
   procedure Put_Trim (S : String) is
   begin
      if S'First <= S'Last and then S (S'First) = ' ' then
         Put (S (S'First + 1 .. S'Last));
      else
         Put (S);
      end if;
   end Put_Trim;

   procedure Put_Uns32 (V : Uns32) is
   begin
      Put_Trim (Uns32'Image (V));
   end Put_Uns32;

   procedure Put_Type (W : Width) is
   begin
      if W = 1 then
         Put ("std_logic");
      else
         Put ("std_logic_vector (");
         if W = 0 then
            Put ("-1");
         else
            Put_Uns32 (W - 1);
         end if;
         Put (" downto 0)");
      end if;
   end Put_Type;

   procedure Put_Id (N : Name_Id) is
   begin
      Put (Name_Table.Image (N));
   end Put_Id;

   procedure Put_Name_Version (N : Sname) is
   begin
      Put_Uns32 (Get_Sname_Version (N));
   end Put_Name_Version;

   procedure Put_Name_1 (N : Sname)
   is
      Prefix : Sname;
   begin
      --  Do not crash on No_Name.
      if N = No_Sname then
         Put ("*nil*");
         return;
      end if;

      Prefix := Get_Sname_Prefix (N);

      case Get_Sname_Kind (N) is
         when Sname_User =>
            if Prefix = No_Sname then
               Put ("\");
            else
               Put_Name_1 (Prefix);
               Put (".");
            end if;
            Put_Id (Get_Sname_Suffix (N));
         when Sname_Artificial =>
            if Prefix = No_Sname then
               Put ("$");
            else
               Put_Name_1 (Prefix);
               Put (".");
            end if;
            Put (Image (Get_Sname_Suffix (N)));
         when Sname_Version =>
            Put_Name_1 (Prefix);
            Put ("%");
            Put_Name_Version (N);
      end case;
   end Put_Name_1;

   procedure Put_Name (N : Sname) is
   begin
      --  Do not crash on No_Name.
      if N = No_Sname then
         Put ("*nil*");
         return;
      end if;

      if Get_Sname_Kind (N) = Sname_User
        and then Get_Sname_Prefix (N) = No_Sname
      then
         Put (Name_Table.Image (Get_Sname_Suffix (N)));
      else
         Put_Name_1 (N);
      end if;
   end Put_Name;

   procedure Put_Interface_Name (N : Sname) is
   begin
      --  Do not crash on No_Name.
      if N = No_Sname then
         Put ("*nil*");
         return;
      end if;

      if Get_Sname_Kind (N) = Sname_Artificial
        and then Get_Sname_Prefix (N) = No_Sname
      then
         Put (Name_Table.Image (Get_Sname_Suffix (N)));
      else
         Put ("*err*");
      end if;
   end Put_Interface_Name;

   procedure Disp_Entity (M : Module)
   is
      First : Boolean;
   begin
      --  Module id and name.
      Put_Line ("library ieee;");
      Put_Line ("use ieee.std_logic_1164.all;");
      Put_Line ("use ieee.numeric_std.all;");
      New_Line;
      Put ("entity ");
      Put_Name (Get_Name (M));
      Put_Line (" is");

      --  Ports.
      First := True;
      for P of Ports_Desc (M) loop
         if First then
            Put_Line ("  port (");
            First := False;
         else
            Put_Line (";");
         end if;
         Put ("    ");
         Put_Name (P.Name);
         Put (" : ");
         case P.Dir is
            when Port_In =>
               Put ("in");
            when Port_Out =>
               Put ("out");
            when Port_Inout =>
               Put ("inout");
         end case;
         Put (' ');
         Put_Type (P.W);
      end loop;
      if not First then
         Put_Line (");");
      end if;

      Put ("end entity ");
      Put_Name (Get_Name (M));
      Put_Line (";");
      New_Line;
   end Disp_Entity;

   procedure Disp_Net_Name (N : Net) is
   begin
      if N = No_Net then
         Put ("<unassigned>");
         return;
      end if;

      declare
         Inst : constant Instance := Get_Parent (N);
         Idx : constant Port_Idx := Get_Port_Idx (N);
         Inst_Name : Sname;
         Port_Name : Sname;
      begin
         if Is_Self_Instance (Inst) then
            Put_Name (Get_Input_Desc (Get_Module (Inst), Idx).Name);
         else
            Inst_Name := Get_Name (Inst);
            Port_Name := Get_Output_Desc (Get_Module (Inst), Idx).Name;
            case Get_Sname_Kind (Inst_Name) is
               when Sname_Version =>
                  Put ("net_");
                  Put_Name_Version (Inst_Name);
                  Put ("_");
                  Put_Interface_Name (Port_Name);
               when Sname_User =>
                  Put_Id (Get_Sname_Suffix (Inst_Name));
               when others =>
                  raise Internal_Error;
            end case;
         end if;
      end;
   end Disp_Net_Name;

   procedure Disp_Instance_Gate (Inst : Instance)
   is
      Imod : constant Module := Get_Module (Inst);
      Idx : Port_Idx;
      P_Idx : Param_Idx;
      Name : Sname;
      First : Boolean;
   begin
      Put ("  ");
      Name := Get_Name (Inst);
      if Get_Sname_Kind (Name) = Sname_Version then
         Put ("inst_");
         Put_Name_Version (Name);
      else
         Put_Name (Name);
      end if;
      Put (" : gsynth.gate_");
      --  Gate name
      Name := Get_Name (Imod);
      pragma Assert (Get_Sname_Kind (Name) = Sname_Artificial
                       and then Get_Sname_Prefix (Name) = No_Sname);
      Put_Id (Get_Sname_Suffix (Name));

      if Get_Nbr_Params (Imod) /= 0 then
         Put_Line (" generic map (");
         First := True;
         Idx := 0;
         for P in Params (Inst) loop
            if First then
               First := False;
            else
               Put_Line (",");
            end if;
            Put ("    ");
            P_Idx := Get_Param_Idx (P);
            Put_Interface_Name (Get_Param_Desc (Imod, P_Idx).Name);
            Put (" => ");
            Put_Uns32 (Get_Param_Uns32 (Inst, P_Idx));
         end loop;
         Put_Line (")");
         Put_Line ("    port map (");
      else
         Put_Line (" port map (");
      end if;

      First := True;
      --  Inputs
      Idx := 0;
      for I of Inputs (Inst) loop
         if First then
            First := False;
         else
            Put_Line (",");
         end if;
         Put ("    ");
         Put_Interface_Name (Get_Input_Desc (Imod, Idx).Name);
         Idx := Idx + 1;
         Put (" => ");
         Disp_Net_Name (Get_Driver (I));
      end loop;
      --  Outputs
      Idx := 0;
      for O of Outputs (Inst) loop
         if First then
            First := False;
         else
            Put_Line (", ");
         end if;
         Put ("    ");
         Put_Interface_Name (Get_Output_Desc (Imod, Idx).Name);
         Idx := Idx + 1;
         Put (" => ");
         Disp_Net_Name (O);
      end loop;
      Put_Line (");");
   end Disp_Instance_Gate;

   Bchar : constant array (Uns32 range 0 .. 3) of Character := "01ZX";

   function Get_Lit_Quote (Wd : Width) return Character is
   begin
      if Wd = 1 then
         return ''';
      else
         return '"';
      end if;
   end Get_Lit_Quote;

   procedure Disp_Binary_Lit (Va : Uns32; Zx : Uns32; Wd : Width)
   is
      W : constant Natural := Natural (Wd);
      Q : constant Character := Get_Lit_Quote (Wd);
   begin
      Put (Q);
      for I in 1 .. W loop
         Put (Bchar (((Va / 2**(W - I)) and 1)
                     + ((Zx / 2**(W - I)) and 1) * 2));
      end loop;
      Put (Q);
   end Disp_Binary_Lit;

   procedure Disp_X_Lit (W : Width)
   is
      Q : constant Character := Get_Lit_Quote (W);
   begin
      Put (Q);
      Put ((1 .. Natural (W) => 'X'));
      Put (Q);
   end Disp_X_Lit;

   procedure Disp_Lit (Inst : Instance)
   is
      O : constant Net := Get_Output (Inst, 0);
   begin
      case Get_Id (Inst) is
         when Id_Const_UB32 =>
            Disp_Binary_Lit (Get_Param_Uns32 (Inst, 0), 0,  Get_Width (O));
         when Id_Const_UL32 =>
            Disp_Binary_Lit (Get_Param_Uns32 (Inst, 0),
                             Get_Param_Uns32 (Inst, 1),
                             Get_Width (O));
         when others =>
            raise Internal_Error;
      end case;
   end Disp_Lit;

   type Conv_Type is (Conv_None, Conv_Unsigned);

   procedure Disp_Net_Expr (N : Net; Conv : Conv_Type)
   is
      Inst : Instance;
   begin
      if N = No_Net then
         Put ("<unassigned>");
         return;
      end if;

      Inst := Get_Parent (N);
      if Flag_Merge_Lit and then Is_Const (Get_Id (Inst)) then
         case Conv is
            when Conv_None =>
               Disp_Lit (Inst);
            when Conv_Unsigned =>
               Put ("unsigned'(");
               Disp_Lit (Inst);
               Put (")");
         end case;
      else
         case Conv is
            when Conv_None =>
               Disp_Net_Name (N);
            when Conv_Unsigned =>
               Put ("unsigned (");
               Disp_Net_Name (N);
               Put (")");
         end case;
      end if;
   end Disp_Net_Expr;

   NL : constant Character := ASCII.LF;

   procedure Disp_Template (S : String; Inst : Instance)
   is
      I : Positive;
      C : Character;
      Idx : Port_Idx;
      N : Net;
      Conv : Conv_Type;
   begin
      I := S'First;
      while I <= S'Last loop
         C := S (I);
         if C = '\' then
            I := I + 1;
            if S (I) = 'u' then
               Conv := Conv_Unsigned;
               I := I + 1;
            else
               Conv := Conv_None;
            end if;
            Idx := Character'Pos (S (I + 1)) - Character'Pos ('0');
            case S (I) is
               when 'o' =>
                  N := Get_Output (Inst, Idx);
               when 'i' =>
                  N := Get_Input_Net (Inst, Idx);
               when others =>
                  raise Internal_Error;
            end case;
            Disp_Net_Expr (N, Conv);
            I := I + 2;
         else
            Put (C);
            I := I + 1;
         end if;
      end loop;
   end Disp_Template;

   procedure Disp_Instance_Inline (Inst : Instance)
   is
      Imod : constant Module := Get_Module (Inst);
   begin
      case Get_Id (Imod) is
         when Id_Output =>
            Disp_Template ("  \o0 <= \i0; -- (output)" & NL, Inst);
         when Id_Signal =>
            Disp_Template ("  \o0 <= \i0; -- (signal)" & NL, Inst);
         when Id_Not =>
            Disp_Template ("  \o0 <= not \i0;" & NL, Inst);
         when Id_Extract =>
            declare
               O : constant Net := Get_Output (Inst, 0);
               Wd : constant Width := Get_Width (O);
               Off : constant Uns32 := Get_Param_Uns32 (Inst, 0);
            begin
               Disp_Template ("  \o0 <= \i0 (", Inst);
               if Wd > 1 then
                  Put_Uns32 (Off + Wd - 1);
                  Put (" downto ");
               end if;
               Put_Uns32 (Off);
               Put_Line (");");
            end;
         when Id_Const_UB32 =>
            declare
               O : constant Net := Get_Output (Inst, 0);
            begin
               Put ("  ");
               Disp_Net_Name (O);
               Put (" <= ");
               Disp_Binary_Lit (Get_Param_Uns32 (Inst, 0), 0,  Get_Width (O));
               Put_Line (";");
            end;
         when Id_Const_UL32 =>
            declare
               O : constant Net := Get_Output (Inst, 0);
            begin
               Put ("  ");
               Disp_Net_Name (O);
               Put (" <= ");
               Disp_Binary_Lit (Get_Param_Uns32 (Inst, 0),
                                Get_Param_Uns32 (Inst, 1),
                                Get_Width (O));
               Put_Line (";");
            end;
         when Id_Adff =>
            Disp_Template ("  process (\i0, \i2)" & NL &
                           "  begin" & NL &
                           "    if \i2 = '1' then" & NL &
                           "      \o0 <= \i3;" & NL &
                           "    elsif rising_edge (\i0) then" & NL &
                           "      \o0 <= \i1;" & NL &
                           "    end if;" & NL &
                           "  end process;" & NL, Inst);
         when Id_Dff =>
            Disp_Template ("  process (\i0)" & NL &
                           "  begin" & NL &
                           "    if rising_edge (\i0) then" & NL &
                           "      \o0 <= \i1;" & NL &
                           "    end if;" & NL &
                           "  end process;" & NL, Inst);
         when Id_Mux2 =>
            Disp_Template ("  \o0 <= \i1 when \i0 = '0' else \i2;" & NL, Inst);
         when Id_Mux4 =>
            Disp_Template ("  with \i0 select \o0 <=" & NL &
                           "    \i1 when ""00""," & NL &
                           "    \i2 when ""01""," & NL &
                           "    \i3 when ""10""," & NL &
                           "    \i4 when ""11""," & NL, Inst);
            Put ("    ");
            Disp_X_Lit (Get_Width (Get_Output (Inst, 0)));
            Put_Line (" when others;");
         when Id_Add =>
            Disp_Template ("  \o0 <= std_logic_vector (\ui0 + \ui1);" & NL,
                           Inst);
         when Id_Sub =>
            Disp_Template ("  \o0 <= std_logic_vector (\ui0 - \ui1);" & NL,
                           Inst);
         when Id_Ult =>
            Disp_Template ("  \o0 <= '1' when \ui0 < \ui1 else '0';" & NL,
                           Inst);
         when Id_Eq =>
            Disp_Template ("  \o0 <= '1' when \i0 = \i1 else '0';" & NL, Inst);
         when Id_Or =>
            Disp_Template ("  \o0 <= \i0 or \i1;" & NL, Inst);
         when Id_And =>
            Disp_Template ("  \o0 <= \i0 and \i1;" & NL, Inst);
         when Id_Concat2 =>
            Disp_Template ("  \o0 <= \i0 & \i1;" & NL, Inst);
         when Id_Concat4 =>
            Disp_Template ("  \o0 <= \i0 & \i1 & \i2 & \i3;" & NL, Inst);
         when Id_Utrunc
           | Id_Strunc =>
            declare
               W : constant Width := Get_Width (Get_Output (Inst, 0));
            begin
               Disp_Template ("  \o0 <= \i0 (", Inst);
               Put_Uns32 (W - 1);
               Put_Line (" downto 0);");
            end;
         when Id_Uextend =>
            declare
               W : constant Width := Get_Width (Get_Output (Inst, 0));
            begin
               Disp_Template ("  \o0 <= std_logic_vector (resize (\ui0, ",
                              Inst);
               Put_Uns32 (W);
               Put_Line ("));");
            end;
         when others =>
            Disp_Instance_Gate (Inst);
      end case;
   end Disp_Instance_Inline;

   procedure Disp_Architecture (M : Module) is
   begin
      Put ("architecture rtl of ");
      Put_Name (Get_Name (M));
      Put_Line (" is");

      --  Dummy display:
      --  * generate one signal per net
      --  * generate instances

      --  Display signal declarations.
      --  There are as many signals as gate outputs.
      for Inst of Instances (M) loop
         if not Is_Self_Instance (Inst)
           and then not (Flag_Merge_Lit and then Is_Const (Get_Id (Inst)))
         then
            for N of Outputs (Inst) loop
               Put ("  signal ");
               Disp_Net_Name (N);
               Put (" : ");
               Put_Type (Get_Width (N));
               Put_Line (";");
            end loop;
         end if;
      end loop;

      Put_Line ("begin");

      --  Output assignments.
      declare
         Inst : constant Instance := Get_Self_Instance (M);
         Idx : Port_Idx;
      begin
         Idx := 0;
         for I of Inputs (Inst) loop
            Put ("  ");
            Put_Name (Get_Output_Desc (M, Idx).Name);
            Put (" <= ");
            Disp_Net_Name (Get_Driver (I));
            Put_Line (";");
            Idx := Idx + 1;
         end loop;
      end;

      for Inst of Instances (M) loop
         if not (Flag_Merge_Lit and then Is_Const (Get_Id (Inst))) then
            Disp_Instance_Inline (Inst);
         end if;
      end loop;

      Put_Line ("end rtl;");
      New_Line;
   end Disp_Architecture;

   procedure Disp_Vhdl (M : Module; Is_Top : Boolean) is
   begin
      for S of Sub_Modules (M) loop
         if Get_Id (S) >= Id_User_None then
            Disp_Vhdl (S, False);
         end if;
      end loop;

      if not Is_Top then
         Disp_Entity (M);
         Disp_Architecture (M);
      end if;
   end Disp_Vhdl;

   procedure Disp_Vhdl (M : Module) is
   begin
      Disp_Vhdl (M, True);
   end Disp_Vhdl;
end Netlists.Disp_Vhdl;