aboutsummaryrefslogtreecommitdiffstats
path: root/src/synth/elab-vhdl_stmts.adb
diff options
context:
space:
mode:
Diffstat (limited to 'src/synth/elab-vhdl_stmts.adb')
-rw-r--r--src/synth/elab-vhdl_stmts.adb231
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;