diff options
Diffstat (limited to 'src/synth/elab-vhdl_stmts.adb')
-rw-r--r-- | src/synth/elab-vhdl_stmts.adb | 231 |
1 files changed, 231 insertions, 0 deletions
diff --git a/src/synth/elab-vhdl_stmts.adb b/src/synth/elab-vhdl_stmts.adb new file mode 100644 index 000000000..d3667b0e4 --- /dev/null +++ b/src/synth/elab-vhdl_stmts.adb @@ -0,0 +1,231 @@ +-- Elaborate statements +-- Copyright (C) 2021 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, see <gnu.org/licenses>. + +with Types; use Types; + +with Vhdl.Errors; use Vhdl.Errors; +with Vhdl.Utils; use Vhdl.Utils; + +with Elab.Vhdl_Objtypes; use Elab.Vhdl_Objtypes; +with Elab.Vhdl_Values; use Elab.Vhdl_Values; +with Elab.Vhdl_Types; use Elab.Vhdl_Types; +with Elab.Vhdl_Decls; use Elab.Vhdl_Decls; +with Elab.Vhdl_Insts; use Elab.Vhdl_Insts; +with Elab.Vhdl_Expr; use Elab.Vhdl_Expr; + +package body Elab.Vhdl_Stmts is + function Elab_Generate_Statement_Body (Syn_Inst : Synth_Instance_Acc; + Bod : Node; + Config : Node; + Iterator : Node := Null_Node; + Iterator_Val : Valtyp := No_Valtyp) + return Synth_Instance_Acc + is + Decls_Chain : constant Node := Get_Declaration_Chain (Bod); + Bod_Inst : Synth_Instance_Acc; + begin + Bod_Inst := Make_Elab_Instance (Syn_Inst, Bod, Config); + + if Iterator /= Null_Node then + -- Add the iterator (for for-generate). + Create_Object (Bod_Inst, Iterator, Iterator_Val); + end if; + + Elab_Declarations (Bod_Inst, Decls_Chain); + + Elab_Concurrent_Statements + (Bod_Inst, Get_Concurrent_Statement_Chain (Bod)); + + return Bod_Inst; + end Elab_Generate_Statement_Body; + + procedure Elab_For_Generate_Statement + (Syn_Inst : Synth_Instance_Acc; Stmt : Node) + is + Iterator : constant Node := Get_Parameter_Specification (Stmt); + Bod : constant Node := Get_Generate_Statement_Body (Stmt); + Configs : constant Node := Get_Generate_Block_Configuration (Bod); + It_Type : constant Node := Get_Declaration_Type (Iterator); + Gen_Inst : Synth_Instance_Acc; + Sub_Inst : Synth_Instance_Acc; + Config : Node; + It_Rng : Type_Acc; + Val : Valtyp; + Ival : Valtyp; + Len : Uns32; + begin + if It_Type /= Null_Node then + Synth_Subtype_Indication (Syn_Inst, It_Type); + end if; + + -- Initial value. + It_Rng := Get_Subtype_Object (Syn_Inst, Get_Type (Iterator)); + Len := Get_Range_Length (It_Rng.Drange); + Val := Create_Value_Discrete (It_Rng.Drange.Left, It_Rng); + + Gen_Inst := Make_Elab_Generate_Instance + (Syn_Inst, Stmt, Configs, Natural (Len)); + + Create_Sub_Instance (Syn_Inst, Stmt, Gen_Inst); + + for I in 1 .. Len loop + -- Find and apply the config block. + declare + Spec : Node; + begin + Config := Configs; + while Config /= Null_Node loop + Spec := Get_Block_Specification (Config); + case Get_Kind (Spec) is + when Iir_Kind_Simple_Name => + exit; + when others => + Error_Kind ("elab_for_generate_statement", Spec); + end case; + Config := Get_Prev_Block_Configuration (Config); + end loop; + Apply_Block_Configuration (Config, Bod); + end; + + -- Create a copy of the current iterator value for the generate + -- block. + Ival := Create_Value_Discrete (Read_Discrete (Val), It_Rng); + + Sub_Inst := Elab_Generate_Statement_Body + (Syn_Inst, Bod, Config, Iterator, Ival); + Set_Generate_Sub_Instance (Gen_Inst, Positive (I), Sub_Inst); + + Update_Index (It_Rng.Drange, Val); + end loop; + end Elab_For_Generate_Statement; + + procedure Elab_If_Generate_Statement + (Syn_Inst : Synth_Instance_Acc; Stmt : Node) + is + Gen : Node; + Bod : Node; + Icond : Node; + Cond : Valtyp; + Config : Node; + Sub_Inst : Synth_Instance_Acc; + begin + Gen := Stmt; + + loop + Icond := Get_Condition (Gen); + if Icond /= Null_Node then + Cond := Exec_Expression (Syn_Inst, Icond); + Strip_Const (Cond); + else + -- It is the else generate. + Cond := No_Valtyp; + end if; + if Cond = No_Valtyp or else Read_Discrete (Cond) = 1 then + Bod := Get_Generate_Statement_Body (Gen); + Config := Get_Generate_Block_Configuration (Bod); + + Apply_Block_Configuration (Config, Bod); + Sub_Inst := Elab_Generate_Statement_Body (Syn_Inst, Bod, Config); + Create_Sub_Instance (Syn_Inst, Bod, Sub_Inst); + return; + end if; + Gen := Get_Generate_Else_Clause (Gen); + exit when Gen = Null_Node; + end loop; + + -- Not generated. + Create_Sub_Instance (Syn_Inst, Stmt, null); + end Elab_If_Generate_Statement; + + procedure Elab_Block_Statement (Syn_Inst : Synth_Instance_Acc; Blk : Node) + is + Blk_Inst : Synth_Instance_Acc; + begin + -- No support for guard or header. + if Get_Block_Header (Blk) /= Null_Node + or else Get_Guard_Decl (Blk) /= Null_Node + then + raise Internal_Error; + end if; + + Apply_Block_Configuration + (Get_Block_Block_Configuration (Blk), Blk); + + Blk_Inst := Make_Elab_Instance (Syn_Inst, Blk, Null_Iir); + Create_Sub_Instance (Syn_Inst, Blk, Blk_Inst); + + Elab_Declarations (Blk_Inst, Get_Declaration_Chain (Blk)); + Elab_Concurrent_Statements + (Blk_Inst, Get_Concurrent_Statement_Chain (Blk)); + end Elab_Block_Statement; + + procedure Elab_Concurrent_Statement + (Syn_Inst : Synth_Instance_Acc; Stmt : Node) is + begin + case Get_Kind (Stmt) is + when Iir_Kinds_Process_Statement => + null; + when Iir_Kind_Concurrent_Simple_Signal_Assignment + | Iir_Kind_Concurrent_Selected_Signal_Assignment + | Iir_Kind_Concurrent_Conditional_Signal_Assignment + | Iir_Kind_Concurrent_Assertion_Statement + | Iir_Kind_Concurrent_Procedure_Call_Statement + | Iir_Kind_Psl_Default_Clock + | Iir_Kind_Psl_Restrict_Directive + | Iir_Kind_Psl_Assume_Directive + | Iir_Kind_Psl_Assert_Directive + | Iir_Kind_Psl_Cover_Directive + | Iir_Kind_Psl_Declaration => + null; + when Iir_Kind_Component_Instantiation_Statement => + if Is_Component_Instantiation (Stmt) then + Elab_Component_Instantiation_Statement (Syn_Inst, Stmt); + else + Elab_Design_Instantiation_Statement (Syn_Inst, Stmt); + end if; + + when Iir_Kind_For_Generate_Statement => + Elab_For_Generate_Statement (Syn_Inst, Stmt); + + when Iir_Kind_If_Generate_Statement => + Elab_If_Generate_Statement (Syn_Inst, Stmt); + + when Iir_Kind_Block_Statement => + Elab_Block_Statement (Syn_Inst, Stmt); + + when others => + Error_Kind ("elab_concurrent_statement", Stmt); + end case; + end Elab_Concurrent_Statement; + + procedure Elab_Concurrent_Statements + (Syn_Inst : Synth_Instance_Acc; Chain : Node) + is + Stmt : Node; + begin + if Chain = Null_Node then + return; + end if; + + Stmt := Chain; + while Stmt /= Null_Node loop + Elab_Concurrent_Statement (Syn_Inst, Stmt); + Stmt := Get_Chain (Stmt); + end loop; + end Elab_Concurrent_Statements; +end Elab.Vhdl_Stmts; |