aboutsummaryrefslogtreecommitdiffstats
path: root/src/synth/synth-expr.adb
diff options
context:
space:
mode:
Diffstat (limited to 'src/synth/synth-expr.adb')
-rw-r--r--src/synth/synth-expr.adb92
1 files changed, 92 insertions, 0 deletions
diff --git a/src/synth/synth-expr.adb b/src/synth/synth-expr.adb
index c5bc9317b..0e3849149 100644
--- a/src/synth/synth-expr.adb
+++ b/src/synth/synth-expr.adb
@@ -2057,6 +2057,94 @@ package body Synth.Expr is
end Synth_Psl_Fell;
+ function Synth_Onehot0 (Ctxt : Context_Acc; DffCurr : Net; Call : Node;
+ Vlen : Uns32)
+ return Net
+ is
+ DffZero : Net;
+ DffOne : Net;
+ DffOneHot0 : Net;
+ Res : Net;
+ begin
+ -- Create a constant vector of 0 for comparing
+ DffZero := Build2_Const_Uns(Ctxt, 0, Vlen);
+
+ -- Create vector of value 1 for subtraction
+ DffOne := Build2_Const_Uns(Ctxt, 1, Vlen);
+
+ -- Subtraction -> v - 1
+ DffOneHot0 := Build_Dyadic (Ctxt, Id_Sub, DffCurr, DffOne);
+ Set_Location (DffOneHot0, Call);
+
+ -- Binary And -> v & (v - 1)
+ DffOneHot0 := Build_Dyadic (Ctxt, Id_And, DffCurr, DffOneHot0);
+ Set_Location (DffOneHot0, Call);
+
+ -- Compare with 0 -> (v & (v - 1)) == 0
+ Res := Build_Compare (Ctxt, Id_Eq, DffOneHot0, DffZero);
+ Set_Location (Res, Call);
+
+ return Res;
+ end Synth_Onehot0;
+
+ function Synth_Psl_Onehot (Syn_Inst : Synth_Instance_Acc; Call : Node)
+ return Valtyp
+ is
+ Ctxt : constant Context_Acc := Get_Build (Syn_Inst);
+ Expr : Valtyp;
+ DffCurr : Net;
+ DffCurrIsNotZero : Net;
+ DffOneHot0 : Net;
+ Res : Net;
+ Vlen : Uns32;
+ begin
+ -- Get parameter & its length
+ Expr := Synth_Expression (Syn_Inst, Get_Expression (Call));
+ Vlen := Expr.Typ.W;
+
+ -- First get net of parameter
+ DffCurr := Get_Net (Ctxt, Expr);
+ Set_Location (DffCurr, Call);
+
+ -- Compare parameter with 0 -> v != 0
+ DffCurrIsNotZero := Build_Compare (Ctxt, Id_Ne, DffCurr,
+ Build2_Const_Uns(Ctxt, 0, Vlen));
+ Set_Location (DffCurrIsNotZero, Call);
+
+ -- Synth onehot0
+ DffOneHot0 := Synth_Onehot0 (Ctxt, DffCurr, Call, Vlen);
+ Set_Location (DffOneHot0, Call);
+
+ -- Final Binary And -> (v != 0) & ((v & (v - 1)) == 0)
+ Res := Build_Dyadic (Ctxt, Id_And, DffOneHot0, DffCurrIsNotZero);
+ Set_Location (Res, Call);
+
+ return Create_Value_Net (Res, Boolean_Type);
+ end Synth_Psl_Onehot;
+
+ function Synth_Psl_Onehot0 (Syn_Inst : Synth_Instance_Acc; Call : Node)
+ return Valtyp
+ is
+ Ctxt : constant Context_Acc := Get_Build (Syn_Inst);
+ Expr : Valtyp;
+ Vlen : Uns32;
+ DffCurr : Net;
+ Res : Net;
+ begin
+ -- Get parameter & its length
+ Expr := Synth_Expression (Syn_Inst, Get_Expression (Call));
+ Vlen := Expr.Typ.W;
+
+ -- First get net of parameter
+ DffCurr := Get_Net (Ctxt, Expr);
+ Set_Location (DffCurr, Call);
+
+ -- Synth onehot0
+ Res := Synth_Onehot0 (Ctxt, DffCurr, Call, Vlen);
+
+ return Create_Value_Net (Res, Boolean_Type);
+ end Synth_Psl_Onehot0;
+
subtype And_Or_Module_Id is Module_Id range Id_And .. Id_Or;
function Synth_Short_Circuit (Syn_Inst : Synth_Instance_Acc;
@@ -2425,6 +2513,10 @@ package body Synth.Expr is
return Synth_Psl_Rose(Syn_Inst, Expr);
when Iir_Kind_Psl_Fell =>
return Synth_Psl_Fell(Syn_Inst, Expr);
+ when Iir_Kind_Psl_Onehot =>
+ return Synth_Psl_Onehot(Syn_Inst, Expr);
+ when Iir_Kind_Psl_Onehot0 =>
+ return Synth_Psl_Onehot0(Syn_Inst, Expr);
when Iir_Kind_Overflow_Literal =>
Error_Msg_Synth (+Expr, "out of bound expression");
return No_Valtyp;