diff options
author | Tristan Gingold <tgingold@free.fr> | 2022-08-20 21:37:25 +0200 |
---|---|---|
committer | Tristan Gingold <tgingold@free.fr> | 2022-08-20 21:37:44 +0200 |
commit | 50cc406f59c3b9b063b47b4fada0d6a5e590f03c (patch) | |
tree | f815aadf154b0f26b85e79d990c8b49fb337e3d7 | |
parent | c28f780bc65b54989cccf83b0637113be3964b51 (diff) | |
download | ghdl-50cc406f59c3b9b063b47b4fada0d6a5e590f03c.tar.gz ghdl-50cc406f59c3b9b063b47b4fada0d6a5e590f03c.tar.bz2 ghdl-50cc406f59c3b9b063b47b4fada0d6a5e590f03c.zip |
simul-vhdl_simul: add support for PSL directives
-rw-r--r-- | src/simul/simul-vhdl_simul.adb | 262 | ||||
-rw-r--r-- | src/simul/simul-vhdl_simul.ads | 19 | ||||
-rw-r--r-- | src/synth/synth-vhdl_stmts.adb | 36 | ||||
-rw-r--r-- | src/synth/synth-vhdl_stmts.ads | 6 |
4 files changed, 289 insertions, 34 deletions
diff --git a/src/simul/simul-vhdl_simul.adb b/src/simul/simul-vhdl_simul.adb index 8ba0442ed..1d1a28aba 100644 --- a/src/simul/simul-vhdl_simul.adb +++ b/src/simul/simul-vhdl_simul.adb @@ -23,11 +23,20 @@ with Ada.Unchecked_Deallocation; with Simple_IO; with Utils_IO; +with Vhdl.Types; with Vhdl.Errors; with Vhdl.Utils; +with Vhdl.Std_Package; +with Vhdl.Ieee.Std_Logic_1164; with Vhdl.Sem_Inst; with Vhdl.Canon; +with PSL.Types; use PSL.Types; +with PSL.Nodes; +with PSL.NFAs; +with PSL.NFAs.Utils; +with PSL.Errors; + with Elab.Vhdl_Objtypes; use Elab.Vhdl_Objtypes; with Elab.Vhdl_Values; use Elab.Vhdl_Values; with Elab.Vhdl_Types; @@ -1117,13 +1126,13 @@ package body Simul.Vhdl_Simul is ((Drv.Typ, Sig.Sig), 0, 0, Get_Value_Memtyp (Val)); end Execute_Expression_Association; + function To_Process_State_Acc is new Ada.Unchecked_Conversion + (Grt.Processes.Instance_Acc, Process_State_Acc); + procedure Process_Executer (Self : Grt.Processes.Instance_Acc) is use Simple_IO; - function To_Process_State_Acc is new Ada.Unchecked_Conversion - (Grt.Processes.Instance_Acc, Process_State_Acc); - Process : Process_State_Acc renames To_Process_State_Acc (Self); begin @@ -1254,6 +1263,230 @@ package body Simul.Vhdl_Simul is end if; end Create_Process_Sensitized; + procedure PSL_Process_Executer (Self : Grt.Processes.Instance_Acc); + pragma Convention (C, PSL_Process_Executer); + + procedure PSL_Assert_Finalizer (Self : Grt.Processes.Instance_Acc); + pragma Convention (C, PSL_Assert_Finalizer); + + function Execute_Psl_Expr (Inst : Synth_Instance_Acc; + Expr : PSL_Node; + Eos : Boolean) + return Boolean + is + use Vhdl.Types; + use Vhdl.Utils; + use PSL.Nodes; + begin + case Get_Kind (Expr) is + when N_HDL_Expr + | N_HDL_Bool => + declare + E : constant Vhdl_Node := Get_HDL_Node (Expr); + Rtype : constant Vhdl_Node := Get_Base_Type (Get_Type (E)); + Res : Valtyp; + V : Ghdl_U8; + begin + Res := Synth.Vhdl_Expr.Synth_Expression (Inst, E); + if Rtype = Vhdl.Std_Package.Boolean_Type_Definition then + return Read_U8 (Res.Val.Mem) = 1; + elsif Rtype = Vhdl.Ieee.Std_Logic_1164.Std_Ulogic_Type then + V := Read_U8 (Res.Val.Mem); + return V = 3 or V = 7; -- 1 or H + else + PSL.Errors.Error_Kind ("execute_psl_expr", Expr); + end if; + end; + when N_True => + return True; + when N_EOS => + return Eos; + when N_Not_Bool => + return not Execute_Psl_Expr (Inst, Get_Boolean (Expr), Eos); + when N_And_Bool => + return Execute_Psl_Expr (Inst, Get_Left (Expr), Eos) + and Execute_Psl_Expr (Inst, Get_Right (Expr), Eos); + when N_Or_Bool => + return Execute_Psl_Expr (Inst, Get_Left (Expr), Eos) + or Execute_Psl_Expr (Inst, Get_Right (Expr), Eos); + when others => + PSL.Errors.Error_Kind ("execute_psl_expr", Expr); + end case; + end Execute_Psl_Expr; + + procedure PSL_Process_Executer (Self : Grt.Processes.Instance_Acc) + is + use PSL.NFAs; + + E : constant Process_State_Acc := To_Process_State_Acc (Self); + Nvec : Boolean_Vector (E.States.all'Range); + Marker : Mark_Type; + V : Boolean; + + NFA : PSL_NFA; + S : NFA_State; + S_Num : Nat32; + Ed : NFA_Edge; + Sd : NFA_State; + Sd_Num : Nat32; + begin + -- Exit now if already covered (never set for assertion). + if E.Done then + return; + end if; + + Instance_Pool := Global_Pool'Access; +-- Current_Process := No_Process; + + Mark (Marker, Expr_Pool); + V := Execute_Psl_Expr (E.Instance, Get_PSL_Clock (E.Proc), False); + Release (Marker, Expr_Pool); + if V then + Nvec := (others => False); + case Get_Kind (E.Proc) is + when Iir_Kind_Psl_Cover_Directive + | Iir_Kind_Psl_Endpoint_Declaration => + Nvec (0) := True; + when others => + null; + end case; + + -- For each state: if set, evaluate all outgoing edges. + NFA := Get_PSL_NFA (E.Proc); + S := Get_First_State (NFA); + while S /= No_State loop + S_Num := Get_State_Label (S); + + if E.States (S_Num) then + Ed := Get_First_Src_Edge (S); + while Ed /= No_Edge loop + Sd := Get_Edge_Dest (Ed); + Sd_Num := Get_State_Label (Sd); + + if not Nvec (Sd_Num) then + Mark (Marker, Expr_Pool); + V := Execute_Psl_Expr + (E.Instance, Get_Edge_Expr (Ed), False); + Release (Marker, Expr_Pool); + if V then + Nvec (Sd_Num) := True; + end if; + end if; + + Ed := Get_Next_Src_Edge (Ed); + end loop; + end if; + + S := Get_Next_State (S); + end loop; + + -- Check fail state. + S := Get_Final_State (NFA); + S_Num := Get_State_Label (S); + pragma Assert (S_Num = Get_PSL_Nbr_States (E.Proc) - 1); + case Get_Kind (E.Proc) is + when Iir_Kind_Psl_Assert_Directive => + if Nvec (S_Num) then + Exec_Failed_Assertion + (E.Instance, E.Proc, + "psl assertion", "assertion violation", 2); + end if; + when Iir_Kind_Psl_Assume_Directive => + if Nvec (S_Num) then + Exec_Failed_Assertion + (E.Instance, E.Proc, + "psl assumption", "assumption violation", 2); + end if; + when Iir_Kind_Psl_Cover_Directive => + if Nvec (S_Num) then + if Get_Report_Expression (E.Proc) /= Null_Iir then + Exec_Failed_Assertion + (E.Instance, E.Proc, + "psl cover", "sequence covered", 0); + end if; + E.Done := True; + end if; +-- when Iir_Kind_Psl_Endpoint_Declaration => +-- declare +-- Info : constant Sim_Info_Acc := Get_Info (E.Stmt); +-- begin +-- E.Instance.Objects (Info.Slot).B1 := Ghdl_B1 (Nvec (S_Num)); +-- end; + when others => + Vhdl.Errors.Error_Kind ("PSL_Process_Executer", E.Proc); + end case; + + E.States.all := Nvec; + end if; + + Instance_Pool := null; + Current_Process := null; + end PSL_Process_Executer; + + procedure PSL_Assert_Finalizer (Self : Grt.Processes.Instance_Acc) + is + use PSL.NFAs; + Ent : constant Process_State_Acc := To_Process_State_Acc (Self); + + NFA : constant PSL_NFA := Get_PSL_NFA (Ent.Proc); + S : NFA_State; + E : NFA_Edge; + Sd : NFA_State; + S_Num : Int32; + begin + S := Get_Final_State (NFA); + E := Get_First_Dest_Edge (S); + while E /= No_Edge loop + Sd := Get_Edge_Src (E); + + if PSL.NFAs.Utils.Has_EOS (Get_Edge_Expr (E)) then + + S_Num := Get_State_Label (Sd); + + if Ent.States (S_Num) + and then + Execute_Psl_Expr (Ent.Instance, Get_Edge_Expr (E), True) + then + Exec_Failed_Assertion + (Ent.Instance, Ent.Proc, + "psl assertion", "assertion violation", 2); + exit; + end if; + end if; + + E := Get_Next_Dest_Edge (E); + end loop; + end PSL_Assert_Finalizer; + + procedure Create_PSL (Proc : in out Process_State_Type; + Inst : System.Address) + is + Stmt : constant Node := Proc.Proc; + begin + -- Create the vector. + Proc.States := new Boolean_Vector' + (0 .. Get_PSL_Nbr_States (Stmt) - 1 => False); + Proc.States (0) := True; + + Grt.Processes.Ghdl_Process_Register + (To_Instance_Acc (Inst), PSL_Process_Executer'Access, + null, System.Null_Address); + + case Get_Kind (Proc.Proc) is + when Iir_Kind_Psl_Assert_Directive + | Iir_Kind_Psl_Assume_Directive => + if Get_PSL_EOS_Flag (Proc.Proc) then + Grt.Processes.Ghdl_Finalize_Register + (To_Instance_Acc (Inst), PSL_Assert_Finalizer'Access); + end if; + when Iir_Kind_Psl_Cover_Directive => + -- TODO + null; + when others => + null; + end case; + end Create_PSL; + procedure Create_Processes is use Grt.Processes; @@ -1268,13 +1501,12 @@ package body Simul.Vhdl_Simul is Instance := Processes_Table.Table (I).Inst; Proc := Processes_Table.Table (I).Proc; --- Instance_Pool := Processes_State (I).Pool'Access; --- Instance.Stmt := Get_Sequential_Statement_Chain (Proc); - - Processes_State (I).Top_Instance := Instance; - Processes_State (I).Proc := Proc; - Processes_State (I).Idx := I; - Processes_State (I).Instance := Instance; + Processes_State (I) := (Kind => Kind_Process, + Top_Instance => Instance, + Proc => Proc, + Idx => I, + Instance => Instance, + Pool => <>); Current_Process := Processes_State (I)'Access; Instance_Addr := Processes_State (I)'Address; @@ -1327,6 +1559,16 @@ package body Simul.Vhdl_Simul is Trans_Analyzes.Free_Drivers_List (Driver_List); end; + when Iir_Kind_Psl_Assert_Directive => + Processes_State (I) := (Kind => Kind_PSL, + Top_Instance => Instance, + Proc => Proc, + Idx => I, + Instance => Instance, + Done => False, + States => null); + Create_PSL (Processes_State (I), Processes_State (I)'Address); + when others => Vhdl.Errors.Error_Kind ("create_processes", Proc); end case; diff --git a/src/simul/simul-vhdl_simul.ads b/src/simul/simul-vhdl_simul.ads index a929c3fa6..38d3173f0 100644 --- a/src/simul/simul-vhdl_simul.ads +++ b/src/simul/simul-vhdl_simul.ads @@ -41,19 +41,30 @@ package Simul.Vhdl_Simul is Trace_Residues : Boolean := False; + type Process_Kind is (Kind_Process, Kind_PSL); + + type Boolean_Vector is array (Nat32 range <>) of Boolean; + type Boolean_Vector_Acc is access Boolean_Vector; + -- State associed with each process. - type Process_State_Type is record + type Process_State_Type (Kind : Process_Kind := Kind_Process) is record -- The process instance. Top_Instance : Synth_Instance_Acc := null; Proc : Node := Null_Node; Idx : Process_Index_Type; - -- Memory pool to allocate objects from. - Pool : aliased Areapool; - -- The stack of the process. Instance : Synth_Instance_Acc := null; + + case Kind is + when Kind_Process => + -- Memory pool to allocate objects from. + Pool : Areapool_Acc; + when Kind_PSL => + Done : Boolean; + States: Boolean_Vector_Acc; + end case; end record; type Process_State_Acc is access all Process_State_Type; diff --git a/src/synth/synth-vhdl_stmts.adb b/src/synth/synth-vhdl_stmts.adb index 50aaae65a..eb6ddedaf 100644 --- a/src/synth/synth-vhdl_stmts.adb +++ b/src/synth/synth-vhdl_stmts.adb @@ -3020,12 +3020,13 @@ package body Synth.Vhdl_Stmts is C.Nbr_Ret := C.Nbr_Ret + 1; end Synth_Return_Statement; - procedure Synth_Static_Report (Syn_Inst : Synth_Instance_Acc; Stmt : Node) + procedure Exec_Failed_Assertion (Syn_Inst : Synth_Instance_Acc; + Stmt : Node; + Stmt_Msg : String; + Default_Rep : String; + Default_Severity : Natural) is use Simple_IO; - - Is_Report : constant Boolean := - Get_Kind (Stmt) = Iir_Kind_Report_Statement; Rep_Expr : constant Node := Get_Report_Expression (Stmt); Sev_Expr : constant Node := Get_Severity_Expression (Stmt); Rep : Valtyp; @@ -3051,18 +3052,10 @@ package body Synth.Vhdl_Stmts is Put_Err (Disp_Location (Stmt)); Put_Err (":("); - if Is_Report then - Put_Err ("report"); - else - Put_Err ("assertion"); - end if; + Put_Err (Stmt_Msg); Put_Err (' '); if Sev = No_Valtyp then - if Is_Report then - Sev_V := 0; - else - Sev_V := 2; - end if; + Sev_V := Default_Severity; else Sev_V := Natural (Read_Discrete (Sev)); end if; @@ -3081,7 +3074,7 @@ package body Synth.Vhdl_Stmts is Put_Err ("): "); if Rep = No_Valtyp then - Put_Line_Err ("Assertion violation"); + Put_Line_Err (Default_Rep); else Put_Line_Err (Value_To_String (Rep)); end if; @@ -3090,12 +3083,12 @@ package body Synth.Vhdl_Stmts is Error_Msg_Synth (+Stmt, "error due to assertion failure"); Elab.Debugger.Debug_Error (Syn_Inst, Stmt); end if; - end Synth_Static_Report; + end Exec_Failed_Assertion; procedure Execute_Report_Statement (Inst : Synth_Instance_Acc; Stmt : Node) is begin - Synth_Static_Report (Inst, Stmt); + Exec_Failed_Assertion (Inst, Stmt, "report", "Assertion violation.", 0); end Execute_Report_Statement; -- Return True if EXPR can be evaluated with static values. @@ -3136,7 +3129,8 @@ package body Synth.Vhdl_Stmts is and then (Sev_Expr = Null_Node or else Is_Static_Expr (Inst, Sev_Expr)) then - Synth_Static_Report (Inst, Stmt); + Exec_Failed_Assertion + (Inst, Stmt, "report", "Assertion violation.", 0); end if; end Synth_Dynamic_Report_Statement; @@ -3155,7 +3149,8 @@ package body Synth.Vhdl_Stmts is if Read_Discrete (Cond) = 1 then return; end if; - Synth_Static_Report (Inst, Stmt); + Exec_Failed_Assertion + (Inst, Stmt, "assertion", "Assertion violation.", 2); end Execute_Assertion_Statement; procedure Synth_Dynamic_Assertion_Statement (C : Seq_Context; Stmt : Node) @@ -3448,7 +3443,8 @@ package body Synth.Vhdl_Stmts is end if; if Is_Static (Val.Val) then if Read_Discrete (Val) /= 1 then - Synth_Static_Report (Syn_Inst, Stmt); + Exec_Failed_Assertion + (Syn_Inst, Stmt, "assertion", "Assertion violation.", 2); end if; return; end if; diff --git a/src/synth/synth-vhdl_stmts.ads b/src/synth/synth-vhdl_stmts.ads index f41c8ca0c..3922b9242 100644 --- a/src/synth/synth-vhdl_stmts.ads +++ b/src/synth/synth-vhdl_stmts.ads @@ -105,6 +105,12 @@ package Synth.Vhdl_Stmts is Stmt : Node); procedure Execute_Report_Statement (Inst : Synth_Instance_Acc; Stmt : Node); + procedure Exec_Failed_Assertion (Syn_Inst : Synth_Instance_Acc; + Stmt : Node; + Stmt_Msg : String; + Default_Rep : String; + Default_Severity : Natural); + procedure Init_For_Loop_Statement (Inst : Synth_Instance_Acc; Stmt : Node; Val : out Valtyp); |