diff options
author | Tristan Gingold <tgingold@free.fr> | 2019-09-05 09:10:12 +0200 |
---|---|---|
committer | Tristan Gingold <tgingold@free.fr> | 2019-09-05 09:10:12 +0200 |
commit | f6d49eb62dac359c96aefc79d3d0ae8f907dc8d9 (patch) | |
tree | 09aa6cd0c040f31fba6b1275467059288ee90e52 | |
parent | 0c71b4ee8844742426f96f0dc0b7c09a197c57dd (diff) | |
download | ghdl-f6d49eb62dac359c96aefc79d3d0ae8f907dc8d9.tar.gz ghdl-f6d49eb62dac359c96aefc79d3d0ae8f907dc8d9.tar.bz2 ghdl-f6d49eb62dac359c96aefc79d3d0ae8f907dc8d9.zip |
synth: add netlists.concats
-rw-r--r-- | src/synth/netlists-concats.adb | 87 | ||||
-rw-r--r-- | src/synth/netlists-concats.ads | 46 | ||||
-rw-r--r-- | src/synth/synth-environment.adb | 38 |
3 files changed, 140 insertions, 31 deletions
diff --git a/src/synth/netlists-concats.adb b/src/synth/netlists-concats.adb new file mode 100644 index 000000000..b01308514 --- /dev/null +++ b/src/synth/netlists-concats.adb @@ -0,0 +1,87 @@ +-- Provide a simple way to concat an unknown number of nets. +-- Copyright (C) 2019 Tristan Gingold +-- +-- This file is part of GHDL. +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation; either version 2 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program; if not, write to the Free Software +-- Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +-- MA 02110-1301, USA. + +package body Netlists.Concats is + procedure Append (C : in out Concat_Type; N : Net) is + begin + if C.Len < C.Sarr'Last then + C.Len := C.Len + 1; + C.Sarr (C.Len) := N; + elsif C.Len > C.Sarr'Last then + C.Len := C.Len + 1; + Net_Tables.Append (C.Darr, N); + else + -- Switch to the dynamic array. + C.Len := C.Len + 1; + Net_Tables.Init (C.Darr); + Net_Tables.Set_Last (C.Darr, C.Len); + C.Darr.Table (C.Sarr'Range) := C.Sarr; + C.Darr.Table (C.Len) := N; + end if; + end Append; + + -- Get the concatenation of all nets in C. Reset C. + procedure Build (Ctxt : Context_Acc; C : in out Concat_Type; N : out Net) + is + Inst : Instance; + Wd : Width; + begin + case C.Len is + when Int32'First .. 0 => + raise Internal_Error; + when 1 => + N := C.Sarr (1); + when 2 => + N := Build_Concat2 (Ctxt, C.Sarr (2), C.Sarr (1)); + when 3 => + N := Build_Concat3 (Ctxt, C.Sarr (3), C.Sarr (2), C.Sarr (1)); + when 4 => + N := Build_Concat4 + (Ctxt, C.Sarr (4), C.Sarr (3), C.Sarr (2), C.Sarr (1)); + when 5 .. Static_Last => + Wd := 0; + for I in 1 .. C.Len loop + Wd := Wd + Get_Width (C.Sarr (I)); + end loop; + + N := Build_Concatn (Ctxt, Wd, Uns32 (C.Len)); + Inst := Get_Parent (N); + for I in 1 .. C.Len loop + Connect (Get_Input (Inst, Port_Idx (I - 1)), C.Sarr (I)); + end loop; + when Static_Last + 1 .. Int32'Last => + pragma Assert (C.Len = Net_Tables.Last (C.Darr)); + Wd := 0; + for I in 1 .. C.Len loop + Wd := Wd + Get_Width (C.Darr.Table (I)); + end loop; + + N := Build_Concatn (Ctxt, Wd, Uns32 (C.Len)); + Inst := Get_Parent (N); + for I in Net_Tables.First .. C.Len loop + Connect (Get_Input (Inst, Port_Idx (I - 1)), C.Darr.Table (I)); + end loop; + -- Free the vector. + Net_Tables.Free (C.Darr); + end case; + + C.Len := 0; + end Build; +end Netlists.Concats; diff --git a/src/synth/netlists-concats.ads b/src/synth/netlists-concats.ads new file mode 100644 index 000000000..3b1e9cb93 --- /dev/null +++ b/src/synth/netlists-concats.ads @@ -0,0 +1,46 @@ +-- Provide a simple way to concat an unknown number of nets. +-- Copyright (C) 2019 Tristan Gingold +-- +-- This file is part of GHDL. +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation; either version 2 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program; if not, write to the Free Software +-- Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +-- MA 02110-1301, USA. + +with Dyn_Tables; +with Netlists.Builders; use Netlists.Builders; + +package Netlists.Concats is + type Concat_Type is limited private; + + -- Append net N to C. + procedure Append (C : in out Concat_Type; N : Net); + + -- Get the concatenation of all nets in C. Reset C. + procedure Build (Ctxt : Context_Acc; C : in out Concat_Type; N : out Net); +private + Static_Last : constant Int32 := 16; + + package Net_Tables is new Dyn_Tables + (Table_Component_Type => Net, + Table_Index_Type => Int32, + Table_Low_Bound => 1, + Table_Initial => Integer (Static_Last * 2)); + + type Concat_Type is limited record + Len : Int32 := 0; + Sarr : Net_Tables.Table_Type (1 .. Static_Last); + Darr : Net_Tables.Instance; + end record; +end Netlists.Concats; diff --git a/src/synth/synth-environment.adb b/src/synth/synth-environment.adb index 4c8850a6a..3e5a65b6d 100644 --- a/src/synth/synth-environment.adb +++ b/src/synth/synth-environment.adb @@ -20,6 +20,7 @@ with Netlists.Builders; use Netlists.Builders; with Netlists.Utils; use Netlists.Utils; +with Netlists.Concats; with Errorout; use Errorout; with Synth.Inference; with Synth.Errors; use Synth.Errors; @@ -620,17 +621,15 @@ package body Synth.Environment is -- Build a vector declare - Vec : Net_Tables.Instance; + use Netlists.Concats; + Vec : Concat_Type; Seq : Seq_Assign; P : Partial_Assign; Cur_Off : Uns32; Cur_Wd : Width; - Last : Int32; - Inst : Instance; Res : Net; begin - Net_Tables.Init (Vec); Cur_Off := Off; Cur_Wd := Wd; pragma Assert (Wd > 0); @@ -651,11 +650,11 @@ package body Synth.Environment is -- Found. if Pr.Offset = Cur_Off and then Pw = Cur_Wd then -- No need to extract. - Net_Tables.Append (Vec, Pr.Value); + Append (Vec, Pr.Value); else Cur_Wd := Width'Min (Cur_Wd, Pw - (Cur_Off - Pr.Offset)); - Net_Tables.Append + Append (Vec, Build_Extract (Ctxt, Pr.Value, Cur_Off - Pr.Offset, Cur_Wd)); end if; @@ -678,7 +677,7 @@ package body Synth.Environment is Seq := Get_Assign_Prev (Seq); if Seq = No_Seq_Assign then -- Extract from gate. - Net_Tables.Append + Append (Vec, Build_Extract (Ctxt, Wire.Gate, Cur_Off, Cur_Wd)); exit; @@ -694,30 +693,7 @@ package body Synth.Environment is end loop; -- Concat - Last := Net_Tables.Last (Vec); - case Last is - when Int32'First .. 0 => - raise Internal_Error; - when 1 => - Res := Vec.Table (1); - when 2 => - Res := Build_Concat2 (Ctxt, Vec.Table (2), Vec.Table (1)); - when 3 => - Res := Build_Concat3 - (Ctxt, Vec.Table (3), Vec.Table (2), Vec.Table (1)); - when 4 => - Res := Build_Concat4 - (Ctxt, - Vec.Table (4), Vec.Table (3), Vec.Table (2), Vec.Table (1)); - when 5 .. Int32'Last => - Res := Build_Concatn (Ctxt, Wd, Uns32 (Last)); - Inst := Get_Parent (Res); - for I in Net_Tables.First .. Last loop - Connect (Get_Input (Inst, Port_Idx (I - 1)), Vec.Table (I)); - end loop; - end case; - -- Free the vector and return it. - Net_Tables.Free (Vec); + Build (Ctxt, Vec, Res); return Res; end; end Get_Current_Assign_Value; |