aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorTristan Gingold <tgingold@free.fr>2019-10-15 18:27:35 +0200
committerTristan Gingold <tgingold@free.fr>2019-10-15 18:27:35 +0200
commitebc4f3e50cfd38ffe00efb6c518700ca39972596 (patch)
tree8649f9eeab5c0161907780f91ef49548d6b08966 /src
parent6af56141854f58a12521caa39339ee90f87db64f (diff)
downloadghdl-ebc4f3e50cfd38ffe00efb6c518700ca39972596.tar.gz
ghdl-ebc4f3e50cfd38ffe00efb6c518700ca39972596.tar.bz2
ghdl-ebc4f3e50cfd38ffe00efb6c518700ca39972596.zip
netlists: declare memory gates.
Diffstat (limited to 'src')
-rw-r--r--src/synth/netlists-builders.adb162
-rw-r--r--src/synth/netlists-builders.ads20
-rw-r--r--src/synth/netlists-gates.ads36
3 files changed, 215 insertions, 3 deletions
diff --git a/src/synth/netlists-builders.adb b/src/synth/netlists-builders.adb
index 3b3184a42..c0dd9a40d 100644
--- a/src/synth/netlists-builders.adb
+++ b/src/synth/netlists-builders.adb
@@ -237,9 +237,9 @@ package body Netlists.Builders is
Id_Dyn_Insert, 3, 1, 1);
Ctxt.M_Dyn_Insert := Res;
Outputs := (0 => Create_Output ("o"));
- Inputs := (0 => Create_Input ("i"),
- 1 => Create_Input ("v"),
- 2 => Create_Input ("p"));
+ Inputs := (0 => Create_Input ("v"),
+ 1 => Create_Input ("d"),
+ 2 => Create_Input ("i"));
Set_Port_Desc (Res, Inputs, Outputs);
Set_Param_Desc
(Res, (0 => (New_Sname_Artificial (Get_Identifier ("offset")),
@@ -282,6 +282,61 @@ package body Netlists.Builders is
Set_Port_Desc (Res, Inputs, Outputs);
end Create_Addidx_Module;
+ procedure Create_Memory_Modules (Ctxt : Context_Acc)
+ is
+ Outputs : Port_Desc_Array (0 .. 1);
+ Inputs : Port_Desc_Array (0 .. 4);
+ Res : Module;
+ begin
+ Res := New_User_Module
+ (Ctxt.Design, New_Sname_Artificial (Get_Identifier ("memory")),
+ Id_Memory, 0, 1, 0);
+ Ctxt.M_Memory := Res;
+ Outputs (0 .. 0) := (0 => Create_Output ("ports"));
+ Set_Port_Desc (Res, Port_Desc_Array'(1 .. 0 => <>), Outputs (0 .. 0));
+
+ Res := New_User_Module
+ (Ctxt.Design, New_Sname_Artificial (Get_Identifier ("memory_init")),
+ Id_Memory_Init, 1, 1, 0);
+ Ctxt.M_Memory_Init := Res;
+ Outputs (0 .. 0) := (0 => Create_Output ("ports"));
+ Inputs (0 .. 0) := (0 => Create_Input ("init"));
+ Set_Port_Desc (Res, Inputs (0 .. 0), Outputs (0 .. 0));
+
+ Res := New_User_Module
+ (Ctxt.Design, New_Sname_Artificial (Get_Identifier ("mem_rd")),
+ Id_Mem_Rd, 2, 2, 0);
+ Ctxt.M_Mem_Rd := Res;
+ Inputs (0 .. 1) := (0 => Create_Input ("pport"),
+ 1 => Create_Input ("addr"));
+ Outputs (0 .. 1) := (0 => Create_Output ("nport"),
+ 1 => Create_Output ("data"));
+ Set_Port_Desc (Res, Inputs (0 .. 1), Outputs (0 .. 1));
+
+ Res := New_User_Module
+ (Ctxt.Design, New_Sname_Artificial (Get_Identifier ("mem_rd_sync")),
+ Id_Mem_Rd_Sync, 3, 2, 0);
+ Ctxt.M_Mem_Rd_Sync := Res;
+ Inputs (0 .. 2) := (0 => Create_Input ("pport"),
+ 1 => Create_Input ("addr"),
+ 2 => Create_Input ("clk"));
+ Outputs (0 .. 1) := (0 => Create_Output ("nport"),
+ 1 => Create_Output ("data"));
+ Set_Port_Desc (Res, Inputs (0 .. 2), Outputs (0 .. 1));
+
+ Res := New_User_Module
+ (Ctxt.Design, New_Sname_Artificial (Get_Identifier ("mem_wr_sync")),
+ Id_Mem_Wr_Sync, 5, 1, 0);
+ Ctxt.M_Mem_Wr_Sync := Res;
+ Inputs := (0 => Create_Input ("pport"),
+ 1 => Create_Input ("addr"),
+ 2 => Create_Input ("clk"),
+ 3 => Create_Input ("en"),
+ 4 => Create_Input ("data"));
+ Outputs (0 .. 0) := (0 => Create_Output ("nport"));
+ Set_Port_Desc (Res, Inputs (0 .. 4), Outputs (0 .. 0));
+ end Create_Memory_Modules;
+
procedure Create_Edge_Module (Ctxt : Context_Acc;
Res : out Module;
Name : Name_Id)
@@ -516,6 +571,8 @@ package body Netlists.Builders is
Create_Memidx_Module (Res);
Create_Addidx_Module (Res);
+ Create_Memory_Modules (Res);
+
Create_Monadic_Module (Design, Res.M_Truncate (Id_Utrunc),
Get_Identifier ("utrunc"), Id_Utrunc);
Create_Monadic_Module (Design, Res.M_Truncate (Id_Strunc),
@@ -1013,6 +1070,105 @@ package body Netlists.Builders is
return O;
end Build_Addidx;
+ function Build_Memory (Ctxt : Context_Acc; W : Width) return Net
+ is
+ pragma Assert (W > 0);
+ Inst : Instance;
+ O : Net;
+ begin
+ Inst := New_Internal_Instance (Ctxt, Ctxt.M_Memory);
+ O := Get_Output (Inst, 0);
+ Set_Width (O, W);
+ return O;
+ end Build_Memory;
+
+ function Build_Memory_Init (Ctxt : Context_Acc; W : Width; Init : Net)
+ return Net
+ is
+ pragma Assert (W > 0);
+ pragma Assert (Get_Width (Init) = W);
+ Inst : Instance;
+ O : Net;
+ begin
+ Inst := New_Internal_Instance (Ctxt, Ctxt.M_Memory_Init);
+ O := Get_Output (Inst, 0);
+ Set_Width (O, W);
+ Connect (Get_Input (Inst, 0), Init);
+ return O;
+ end Build_Memory_Init;
+
+ function Build_Mem_Rd (Ctxt : Context_Acc; Pport : Net; Addr : Net)
+ return Instance
+ is
+ Mem_W : constant Width := Get_Width (Pport);
+ pragma Assert (Mem_W > 0);
+ Addr_W : constant Width := Get_Width (Addr);
+ pragma Assert (Addr_W > 0);
+ Data_W : constant Width := Mem_W / Addr_W;
+ pragma Assert (Data_W * Addr_W = Mem_W);
+ Inst : Instance;
+ O : Net;
+ begin
+ Inst := New_Internal_Instance (Ctxt, Ctxt.M_Mem_Rd);
+ O := Get_Output (Inst, 0);
+ Set_Width (O, Data_W);
+ Connect (Get_Input (Inst, 0), Pport);
+ Connect (Get_Input (Inst, 1), Addr);
+ return Inst;
+ end Build_Mem_Rd;
+
+ function Build_Mem_Rd_Sync
+ (Ctxt : Context_Acc; Pport : Net; Addr : Net; Clk : Net)
+ return Instance
+ is
+ Mem_W : constant Width := Get_Width (Pport);
+ pragma Assert (Mem_W > 0);
+ Addr_W : constant Width := Get_Width (Addr);
+ pragma Assert (Addr_W > 0);
+ Data_W : constant Width := Mem_W / Addr_W;
+ pragma Assert (Data_W * Addr_W = Mem_W);
+ pragma Assert (Get_Width (Clk) = 1);
+ Inst : Instance;
+ O : Net;
+ begin
+ Inst := New_Internal_Instance (Ctxt, Ctxt.M_Mem_Rd_Sync);
+ O := Get_Output (Inst, 0);
+ Set_Width (O, Data_W);
+ Connect (Get_Input (Inst, 0), Pport);
+ Connect (Get_Input (Inst, 1), Addr);
+ Connect (Get_Input (Inst, 2), Clk);
+ return Inst;
+ end Build_Mem_Rd_Sync;
+
+ function Build_Mem_Wr_Sync (Ctxt : Context_Acc;
+ Pport : Net;
+ Addr : Net;
+ Clk : Net;
+ En : Net;
+ Data : Net) return Instance
+ is
+ Mem_W : constant Width := Get_Width (Pport);
+ pragma Assert (Mem_W > 0);
+ Addr_W : constant Width := Get_Width (Addr);
+ pragma Assert (Addr_W > 0);
+ Data_W : constant Width := Get_Width (Data);
+ pragma Assert (Data_W * Addr_W = Mem_W);
+ pragma Assert (Get_Width (Clk) = 1);
+ pragma Assert (Get_Width (En) = 1);
+ Inst : Instance;
+ O : Net;
+ begin
+ Inst := New_Internal_Instance (Ctxt, Ctxt.M_Mem_Wr_Sync);
+ O := Get_Output (Inst, 0);
+ Set_Width (O, Data_W);
+ Connect (Get_Input (Inst, 0), Pport);
+ Connect (Get_Input (Inst, 1), Addr);
+ Connect (Get_Input (Inst, 2), Clk);
+ Connect (Get_Input (Inst, 3), En);
+ Connect (Get_Input (Inst, 4), Data);
+ return Inst;
+ end Build_Mem_Wr_Sync;
+
function Build_Object (Ctxt : Context_Acc; M : Module; W : Width) return Net
is
Inst : Instance;
diff --git a/src/synth/netlists-builders.ads b/src/synth/netlists-builders.ads
index be580d392..b202a952c 100644
--- a/src/synth/netlists-builders.ads
+++ b/src/synth/netlists-builders.ads
@@ -139,6 +139,21 @@ package Netlists.Builders is
I : Net; Step : Uns32; Max : Uns32; W : Width) return Net;
function Build_Addidx (Ctxt : Context_Acc; L, R : Net) return Net;
+ function Build_Memory (Ctxt : Context_Acc; W : Width) return Net;
+ function Build_Memory_Init (Ctxt : Context_Acc; W : Width; Init : Net)
+ return Net;
+ function Build_Mem_Rd (Ctxt : Context_Acc; Pport : Net; Addr : Net)
+ return Instance;
+ function Build_Mem_Rd_Sync
+ (Ctxt : Context_Acc; Pport : Net; Addr : Net; Clk : Net)
+ return Instance;
+ function Build_Mem_Wr_Sync (Ctxt : Context_Acc;
+ Pport : Net;
+ Addr : Net;
+ Clk : Net;
+ En : Net;
+ Data : Net) return Instance;
+
function Build_Output (Ctxt : Context_Acc; W : Width) return Net;
function Build_Signal (Ctxt : Context_Acc; Name : Sname; W : Width)
return Net;
@@ -209,6 +224,11 @@ private
M_Dyn_Insert : Module;
M_Memidx : Module;
M_Addidx : Module;
+ M_Memory : Module;
+ M_Memory_Init : Module;
+ M_Mem_Rd : Module;
+ M_Mem_Rd_Sync : Module;
+ M_Mem_Wr_Sync : Module;
M_Assert : Module;
M_Assume : Module;
M_Cover : Module;
diff --git a/src/synth/netlists-gates.ads b/src/synth/netlists-gates.ads
index 7e4339e22..f37b41f67 100644
--- a/src/synth/netlists-gates.ads
+++ b/src/synth/netlists-gates.ads
@@ -159,6 +159,42 @@ package Netlists.Gates is
-- OUT := IN0 + IN1, size extension.
Id_Addidx : constant Module_Id := 72;
+ -- Represent a memory with a fixed size.
+ -- This is not a regular gate as it has only one output, PORTS.
+ -- The width of the output is the size (in bits) of the memory.
+ -- The PORTS links to the first read or write port. There must be only
+ -- one connection. The order is important as it defines the order of
+ -- actions.
+ -- Outputs: PORTS
+ Id_Memory : constant Module_Id := 73;
+
+ -- Same as Id_Memory but with an initial value.
+ Id_Memory_Init : constant Module_Id := 74;
+
+ -- Asynchronous memory read port.
+ -- Inputs: PPORT (previous memory port)
+ -- ADDR
+ -- Outputs: NPORT (next memory port)
+ -- DATA
+ Id_Mem_Rd : constant Module_Id := 75;
+
+ -- Synchronous memory read port.
+ -- Inputs: PPORT (previous memory port)
+ -- ADDR
+ -- CLK
+ -- Outputs: NPORT (next memory port)
+ -- DATA
+ Id_Mem_Rd_Sync : constant Module_Id := 76;
+
+ -- Synchronous memory write port
+ -- Inputs: PPORT (previous memory port)
+ -- ADDR
+ -- CLK
+ -- EN
+ -- DATA
+ -- Outputs: NPORT (next memory port)
+ Id_Mem_Wr_Sync : constant Module_Id := 77;
+
-- Positive/rising edge detector. This is a pseudo gate.
-- A negative edge detector can be made using by negating the clock before
-- the detector.