aboutsummaryrefslogtreecommitdiffstats
path: root/src/synth/netlists-memories.adb
diff options
context:
space:
mode:
authorTristan Gingold <tgingold@free.fr>2020-04-13 11:52:49 +0200
committerTristan Gingold <tgingold@free.fr>2020-04-13 11:52:49 +0200
commit600f62bf08d38607800788f88765e893206ed619 (patch)
treeb055f1a83fe979127d07d8760bdbda842a4c385c /src/synth/netlists-memories.adb
parent7e665fc4dbca47346ae98ae0f2823caa3e5eb1a2 (diff)
downloadghdl-600f62bf08d38607800788f88765e893206ed619.tar.gz
ghdl-600f62bf08d38607800788f88765e893206ed619.tar.bz2
ghdl-600f62bf08d38607800788f88765e893206ed619.zip
synth: handle multi-dim ROMS. Fix #1220
Diffstat (limited to 'src/synth/netlists-memories.adb')
-rw-r--r--src/synth/netlists-memories.adb47
1 files changed, 33 insertions, 14 deletions
diff --git a/src/synth/netlists-memories.adb b/src/synth/netlists-memories.adb
index 195a3ddf1..e0aa5fa1d 100644
--- a/src/synth/netlists-memories.adb
+++ b/src/synth/netlists-memories.adb
@@ -164,6 +164,10 @@ package body Netlists.Memories is
when Id_Dyn_Extract =>
-- Extract step from memidx gate.
Idx := Get_Net_Parent (Get_Input_Net (Extr_Inst, 1));
+ if Get_Id (Idx) = Id_Addidx then
+ -- Multi-dim arrays, lowest index is the first one.
+ Idx := Get_Net_Parent (Get_Input_Net (Idx, 0));
+ end if;
pragma Assert (Get_Id (Idx) = Id_Memidx);
Step := Get_Param_Uns32 (Idx, 0);
@@ -247,7 +251,6 @@ package body Netlists.Memories is
end Count_Memidx;
-- Lower memidx/addidx to simpler gates (concat).
- -- MEM is the memory (used to get its size).
-- MEM_SIZE: size of the memory (in bits).
-- ADDR is the address net with memidx/addidx gates.
-- VAL_WD is the width of the data port.
@@ -311,7 +314,7 @@ package body Netlists.Memories is
pragma Unreferenced (Mem_Depth);
-- Do checks on memidx.
- Last_Size := Mem_Size;
+ Last_Size := 0;
for I in Indexes'Range loop
declare
Inst : constant Instance := Indexes (I).Inst;
@@ -322,10 +325,19 @@ package body Netlists.Memories is
Max_W : constant Width := Clog2 (Max + 1);
Sub_Addr1 : Net;
begin
- -- Check max
+ -- Check max (from previous dimension).
pragma Assert (Max /= 0);
- if (Max + 1) * Step /= Last_Size then
- raise Internal_Error;
+ if I /= Indexes'First then
+ if Last_Size /= Step then
+ raise Internal_Error;
+ end if;
+ end if;
+ Last_Size := (Max + 1) * Step;
+
+ if I = Indexes'First then
+ if Step /= Val_Wd then
+ raise Internal_Error;
+ end if;
end if;
-- Check addr width.
@@ -340,16 +352,13 @@ package body Netlists.Memories is
Sub_Addr1 := Sub_Addr;
end if;
Indexes (I).Addr := Sub_Addr1;
-
- if I = Indexes'Last then
- if Step /= Val_Wd then
- raise Internal_Error;
- end if;
- end if;
- Last_Size := Step;
end;
end loop;
+ if Last_Size /= Mem_Size then
+ raise Internal_Error;
+ end if;
+
-- Lower (just concat addresses).
declare
use Netlists.Concats;
@@ -368,6 +377,7 @@ package body Netlists.Memories is
-- Free addidx and memidx.
declare
N : Net;
+ Inp : Input;
Inst : Instance;
Inst2 : Instance;
begin
@@ -379,12 +389,21 @@ package body Netlists.Memories is
Remove_Instance (Inst);
exit;
when Id_Addidx =>
- Inst2 := Get_Input_Instance (Inst, 0);
+ -- Remove the first input (a memidx).
+ Inp := Get_Input (Inst, 0);
+ Inst2 := Get_Net_Parent (Get_Driver (Inp));
if Get_Id (Inst2) /= Id_Memidx then
raise Internal_Error;
end if;
+ Disconnect (Inp);
Remove_Instance (Inst2);
- N := Get_Input_Net (Inst, 1);
+
+ -- Continue with the second input.
+ Inp := Get_Input (Inst, 1);
+ N := Get_Driver (Inp);
+ Disconnect (Inp);
+
+ -- Remove the addidx.
Remove_Instance (Inst);
when others =>
raise Internal_Error;