diff options
author | Tristan Gingold <tgingold@free.fr> | 2019-10-15 18:27:35 +0200 |
---|---|---|
committer | Tristan Gingold <tgingold@free.fr> | 2019-10-15 18:27:35 +0200 |
commit | ebc4f3e50cfd38ffe00efb6c518700ca39972596 (patch) | |
tree | 8649f9eeab5c0161907780f91ef49548d6b08966 | |
parent | 6af56141854f58a12521caa39339ee90f87db64f (diff) | |
download | ghdl-ebc4f3e50cfd38ffe00efb6c518700ca39972596.tar.gz ghdl-ebc4f3e50cfd38ffe00efb6c518700ca39972596.tar.bz2 ghdl-ebc4f3e50cfd38ffe00efb6c518700ca39972596.zip |
netlists: declare memory gates.
-rw-r--r-- | src/synth/netlists-builders.adb | 162 | ||||
-rw-r--r-- | src/synth/netlists-builders.ads | 20 | ||||
-rw-r--r-- | src/synth/netlists-gates.ads | 36 |
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. |