aboutsummaryrefslogtreecommitdiffstats
path: root/src/synth/netlists-memories.adb
diff options
context:
space:
mode:
authorTristan Gingold <tgingold@free.fr>2020-01-16 18:19:52 +0100
committerTristan Gingold <tgingold@free.fr>2020-01-16 18:19:52 +0100
commit50dfbb841f3a50cb72bd381cc3438327a7b4e2f3 (patch)
treea7c8935472d9cb63cd9335bbce65780a3a6936e2 /src/synth/netlists-memories.adb
parent2bd8625e54e2f0c4a2c0a8400c122f61435fe7ee (diff)
downloadghdl-50dfbb841f3a50cb72bd381cc3438327a7b4e2f3.tar.gz
ghdl-50dfbb841f3a50cb72bd381cc3438327a7b4e2f3.tar.bz2
ghdl-50dfbb841f3a50cb72bd381cc3438327a7b4e2f3.zip
netlists-memories: fix split of memory content. Fix
Diffstat (limited to 'src/synth/netlists-memories.adb')
-rw-r--r--src/synth/netlists-memories.adb135
1 files changed, 131 insertions, 4 deletions
diff --git a/src/synth/netlists-memories.adb b/src/synth/netlists-memories.adb
index c51229d48..fb6fceb79 100644
--- a/src/synth/netlists-memories.adb
+++ b/src/synth/netlists-memories.adb
@@ -1262,6 +1262,130 @@ package body Netlists.Memories is
Len := Idx2 - Idx;
end Off_Array_To_Idx;
+ type Copy_Mode_Type is (Copy_Mode_Bit, Copy_Mode_Val, Copy_Mode_Zx);
+
+ procedure Copy_Const_Content (Src : Instance;
+ Src_Off : Width;
+ Src_Wd : Width;
+ Dst : Instance;
+ Dst_Wd : Width;
+ Depth : Uns32;
+ Mode : Copy_Mode_Type)
+ is
+ function Off_To_Param (Off : Uns32) return Param_Idx
+ is
+ Res : constant Param_Idx := Param_Idx (Off / 32);
+ begin
+ case Mode is
+ when Copy_Mode_Bit =>
+ return Res;
+ when Copy_Mode_Val =>
+ return Res * 2;
+ when Copy_Mode_Zx =>
+ return Res * 2 + 1;
+ end case;
+ end Off_To_Param;
+
+ Boff : Uns32;
+ Nbits : Uns32;
+ Word_Idx : Param_Idx;
+ Word_Off : Uns32;
+
+ Soff : Uns32;
+ Slen : Uns32;
+ Sval : Uns32;
+
+ Doff : Uns32;
+ Dlen : Uns32;
+ Dval : Uns32;
+ begin
+ Boff := Src_Off;
+ Doff := 0;
+ for I in 0 .. Depth - 1 loop
+ Nbits := Dst_Wd;
+ Soff := Boff;
+ while Nbits > 0 loop
+ -- Try to read as much as possible.
+ Word_Idx := Off_To_Param (Soff);
+ Word_Off := Soff mod 32;
+ Slen := 32 - Word_Off;
+ if Slen > Nbits then
+ Slen := Nbits;
+ end if;
+ Sval := Get_Param_Uns32 (Src, Word_Idx);
+ -- Reframe (put at bit 0, mask extra bits).
+ Sval := Shift_Right (Sval, Natural (Word_Off));
+ Sval := Sval and Shift_Right (16#ffff_ffff#,
+ Natural (32 - Slen));
+
+ Soff := Soff + Slen;
+ Nbits := Nbits - Slen;
+
+ -- Store.
+ while Slen > 0 loop
+ Word_Idx := Off_To_Param (Doff);
+ Word_Off := Doff mod 32;
+ Dlen := 32 - Word_Off;
+ if Dlen > Slen then
+ Dlen := Slen;
+ end if;
+ Dval := Sval and Shift_Right (16#ffff_ffff#,
+ Natural (32 - Dlen));
+ Dval := Shift_Left (Dval, Natural (Word_Off));
+ Dval := Dval or Get_Param_Uns32 (Dst, Word_Idx);
+ Set_Param_Uns32 (Dst, Word_Idx, Dval);
+
+ Sval := Shift_Right (Sval, Natural (Dlen));
+ Slen := Slen - Dlen;
+ Doff := Doff + Dlen;
+ end loop;
+ end loop;
+ Boff := Boff + Src_Wd;
+ end loop;
+ end Copy_Const_Content;
+
+ -- From constant net CST (used to initialize a memory), extract DEPTH sub
+ -- words (bits OFF:OFF + WD - 1).
+ -- Used when memories are split.
+ function Extract_Sub_Constant (Ctxt : Context_Acc;
+ Cst : Instance;
+ Cst_Wd : Uns32;
+ Off : Uns32;
+ Wd : Uns32;
+ Depth : Uns32) return Net
+ is
+ pragma Assert (Depth /= 0);
+ Mem_Wd : constant Width := Wd * Depth;
+ Res : Instance;
+ begin
+ case Get_Id (Cst) is
+ when Id_Const_Bit =>
+ Res := Build_Const_Bit (Ctxt, Mem_Wd);
+ Copy_Const_Content (Cst, Off, Cst_Wd, Res, Wd, Depth,
+ Copy_Mode_Bit);
+ return Get_Output (Res, 0);
+ when Id_Const_Log =>
+ Res := Build_Const_Log (Ctxt, Mem_Wd);
+ Copy_Const_Content (Cst, Off, Cst_Wd, Res, Wd, Depth,
+ Copy_Mode_Val);
+ Copy_Const_Content (Cst, Off, Cst_Wd, Res, Wd, Depth,
+ Copy_Mode_Zx);
+ return Get_Output (Res, 0);
+ when Id_Const_UB32 =>
+ declare
+ N : Net;
+ begin
+ N := Build_Const_UB32 (Ctxt, 0, Mem_Wd);
+ Copy_Const_Content
+ (Cst, Off, Cst_Wd, Get_Net_Parent (N), Wd, Depth,
+ Copy_Mode_Bit);
+ return N;
+ end;
+ when others =>
+ raise Internal_Error;
+ end case;
+ end Extract_Sub_Constant;
+
procedure Convert_To_Memory (Ctxt : Context_Acc; Sig : Instance)
is
-- Size of RAM (in bits).
@@ -1451,15 +1575,18 @@ package body Netlists.Memories is
-- 4. Create Memory/Memory_Init from signal/isignal.
for I in 1 .. Nbr_Offs - 1 loop
declare
- Wd : constant Width := (Offs (I + 1) - Offs (I)) * Mem_Depth;
+ Data_Wd : constant Width := Offs (I + 1) - Offs (I);
+ Mem_Wd : constant Width := Data_Wd * Mem_Depth;
begin
case Get_Id (Sig) is
when Id_Isignal =>
Heads (I) := Build_Memory_Init
- (Ctxt, Wd, Build2_Extract (Ctxt, Get_Input_Net (Sig, 1),
- Offs (I), Wd));
+ (Ctxt, Mem_Wd,
+ Extract_Sub_Constant
+ (Ctxt, Get_Input_Instance (Sig, 1),
+ Mem_W, Offs (I), Data_Wd, Mem_Depth));
when Id_Signal =>
- Heads (I) := Build_Memory (Ctxt, Wd);
+ Heads (I) := Build_Memory (Ctxt, Mem_Wd);
when others =>
raise Internal_Error;
end case;