diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/synth/netlists-memories.adb | 107 | 
1 files changed, 75 insertions, 32 deletions
| diff --git a/src/synth/netlists-memories.adb b/src/synth/netlists-memories.adb index a29ec0d33..597df7dee 100644 --- a/src/synth/netlists-memories.adb +++ b/src/synth/netlists-memories.adb @@ -1557,25 +1557,6 @@ package body Netlists.Memories is        end loop;     end Reduce_Extract_Muxes; -   --  Extract the step (equivalent to data width) of a dyn_insert/dyn_extract -   --  address.  This is either a memidx or an addidx gate. -   function Extract_Memidx_Step (Memidx : Instance) return Width -   is -      Inst : Instance; -   begin -      Inst := Memidx; -      loop -         case Get_Id (Inst) is -            when Id_Addidx => -               Inst := Get_Input_Instance (Inst, 1); -            when Id_Memidx => -               return Get_Param_Uns32 (Inst, 0); -            when others => -               raise Internal_Error; -         end case; -      end loop; -   end Extract_Memidx_Step; -     type Off_Array is array (Int32 range <>) of Uns32;     type Off_Array_Acc is access Off_Array; @@ -1747,23 +1728,75 @@ package body Netlists.Memories is        end case;     end Extract_Sub_Constant; +   --  Physical dimension of the memory. +   type Mem_Dim_Type is record +      Data_Wd : Width; +      Depth : Uns32; +      --  Number of dimensions. +      Dim : Natural; +   end record; + +   --  Extract the dim (equivalent to data width) of a dyn_insert/dyn_extract +   --  address.  This is either a memidx or an addidx gate. +   function Extract_Memidx_Dim (Memidx : Instance) return Mem_Dim_Type +   is +      Res : Mem_Dim_Type; +      Inst : Instance; +      Idx : Instance; +   begin +      Inst := Memidx; +      Res := (Data_Wd => 0, Depth => 1, Dim => 0); +      loop +         case Get_Id (Inst) is +            when Id_Addidx => +               --  Handle the memidx, ... +               Idx := Get_Input_Instance (Inst, 0); +               --  ..  and continue with the chain. +               Inst := Get_Input_Instance (Inst, 1); +            when Id_Memidx => +               --  Just handle the memidx. +               Idx := Inst; +               Inst := No_Instance; +            when others => +               raise Internal_Error; +         end case; +         Res.Dim := Res.Dim + 1; +         Res.Data_Wd := Get_Param_Uns32 (Idx, 0); +         Res.Depth := Res.Depth * (Get_Param_Uns32 (Idx, 1) + 1); +         if Inst = No_Instance then +            return Res; +         end if; +      end loop; +   end Extract_Memidx_Dim; +     --  Subroutine of Convert_To_Memory.     --     --  Compute the number of ports (dyn_extract and dyn_insert) and the width     --  of the memory.  Just walk all the gates. -   procedure Compute_Ports_And_Width -     (Sig : Instance; Nbr_Ports : out Int32; Wd : out Width) +   procedure Compute_Ports_And_Dim +     (Sig : Instance; Nbr_Ports : out Int32; Dim : out Mem_Dim_Type)     is -      procedure Add_Port_And_Width (Memidx : Instance) is +      procedure Add_Port_And_Width (Memidx : Instance) +      is +         T : Mem_Dim_Type;        begin           Nbr_Ports := Nbr_Ports + 1; -         if Wd = 0 then -            Wd := Extract_Memidx_Step (Memidx); -         elsif Wd /= Extract_Memidx_Step (Memidx) then -            Info_Msg_Synth (+Sig, "memory %n uses different widths", +         T := Extract_Memidx_Dim (Memidx); +         if Nbr_Ports = 1 then +            Dim := T; +         else +            --  TODO: handle different width and depth. +            if T.Data_Wd /= Dim.Data_Wd then +               Info_Msg_Synth (+Sig, "memory %n uses different widths",                              (1 => +Sig)); -            Nbr_Ports := 0; -            return; +               Nbr_Ports := 0; +               return; +            elsif T.Depth /= Dim.Depth then +               Info_Msg_Synth (+Sig, "memory %n uses different depth", +                            (1 => +Sig)); +               Nbr_Ports := 0; +               return; +            end if;           end if;        end Add_Port_And_Width; @@ -1771,7 +1804,7 @@ package body Netlists.Memories is        Inp2 : Input;     begin        Nbr_Ports := 0; -      Wd := 0; +      Dim.Dim := 0;        --  Top-level loop, for each parallel path of multiport RAMs.        Inp2 := Get_First_Sink (Get_Output (Sig, 0)); @@ -1837,7 +1870,7 @@ package body Netlists.Memories is           end case;           Inp2 := Get_Next_Sink (Inp2);        end loop; -   end Compute_Ports_And_Width; +   end Compute_Ports_And_Dim;     --  Subroutine of Convert_To_Memory.     -- @@ -2166,10 +2199,13 @@ package body Netlists.Memories is        Sig_Name : constant Sname := Get_Instance_Name (Sig); +      Dim : Mem_Dim_Type; +        --  Width of the RAM, computed from the step of memidx. +      --  Width is the length of the data bus.        Mem_W : Width; -      --  Number of addresses of the memory. +      --  Number of elements of the memory.        --  Sz = W * Depth.        Mem_Depth : Uns32; @@ -2193,10 +2229,11 @@ package body Netlists.Memories is        Nbr_Ports := 0;        Mem_W := 0;        Inst := Sig; -      Compute_Ports_And_Width (Sig, Nbr_Ports, Mem_W); +      Compute_Ports_And_Dim (Sig, Nbr_Ports, Dim);        if Nbr_Ports = 0 then           return;        end if; +      Mem_W := Dim.Data_Wd;        if Mem_W = 0 then           --  No ports ? @@ -2216,6 +2253,10 @@ package body Netlists.Memories is        end if;        --  2. Walk to extract offsets/width +      --  NOTE: ideally, there are two kinds of offsets: +      --   * offsets within the width: when the data is a struct +      --   * offsets larger than the size: multiple memories, which may have +      --     different sizes.        Offs := new Off_Array (1 .. 2 * Nbr_Ports);        Extract_Ports_Offsets (Sig, Offs, Nbr_Offs); @@ -2370,6 +2411,7 @@ package body Netlists.Memories is        end case;     end Is_Const_Input; +   --  The main entry point.     procedure Extract_Memories (Ctxt : Context_Acc; M : Module)     is        Dyns : Instance_Tables.Instance; @@ -2433,6 +2475,7 @@ package body Netlists.Memories is        --  Unmark memory gates.        Unmark_Table (Mems); +      --  Convert to RAM or ROM.        for I in Instance_Tables.First .. Instance_Tables.Last (Mems) loop           --  INST is the memorizing instance, ie isignal/signal.           Inst := Mems.Table (I); | 
