575
575
(lvalues (mergesort (vl-idexprlist->names (vl-stmt-cblock-lvalexprs body))))
576
((unless (vl-cblock-pathcheck lvalues body))
577
;; Some reg doesn't get updated in some path, not a combinational
578
;; block, maybe a latch or something.
576
(paths-okp (vl-cblock-pathcheck lvalues body))
578
((when (and (not paths-okp)
579
(not (eq type :vl-always-comb))))
580
;; Some reg doesn't get updated in some path, and we don't know for
581
;; sure that this is supposed to be a combinational block. This
582
;; might be a latch. It's not our job to synthesize it. Just fail,
583
;; no error, no warning. BOZO for better debugging it might be good
584
;; to have a warning here anyway...
588
(if (and (not paths-okp)
589
(eq type :vl-always-comb))
590
(warn :type :vl-tricky-always-comb
591
:msg "~a0: always block does not obviously write to all of ~
592
its registers in every if/else branch."
581
596
;; Otherwise this pretty strongly seems to be intended to be a
582
597
;; combinational always block. At this point it's probably fine to
583
598
;; start issuing warnings.
648
663
:short "Convert a combinational always block into assignments."
649
664
:long "<p>Basic examples of what we're trying to do here:</p>
651
always @(*) ----> assign lhs = condition1 ? expr1
652
if (condition1) : condition2 ? expr2
666
always @(*) ----> assign lhs = condition1 ? {expr1}
667
if (condition1) : condition2 ? {expr2}
668
lhs = expr1; : {expr3}
654
669
else if (condition2)
659
always @(*) ----> assign lhs = condition ? expr2 : expr1
674
always @(*) ----> assign lhs = condition ? {expr2} : {expr1}
672
687
<p>To avoid this, we locally use the @(see stmttemps) transform before trying
673
688
to carry out this expression building. This should ensure that all lhses/rhses
674
are well-typed and have compatible widths.</p>")
689
are well-typed and have compatible widths. The excessive use of concatenations
690
above ensures that everything is unsigned, to avoid creating badly typed
691
@('?:') expressions.</p>
693
<p>Slight twist. If we know that this is supposed to be a combinational always
694
block because it's written with @('always_comb'), then we allow the lhs to not
695
be written in every branch. In this case a Verilog simulator may not trigger
696
any update of the variable, essentially treating it like a latch. However, it
697
seems quite likely that a synthesis tool will not infer a latch. To try to
698
avoid making mistakes here, we want to make sure to drive the variable to Xes
701
<p>To drive the variable to Xes, a simple thing to do is, e.g.,</p>
704
always_comb ---> always_comb
705
if (condition) lhs = XXXX
706
lhs = expr; if (condition)
707
if (condition2) lhs = expr;
708
lhs = expr2; if (condition2)
712
<p>This is safe even if all the branches are covered (in which case we're
713
simply setting the variable to X and then to its real value).</p>")
676
715
(define vl-atomicstmt-cblock-varexpr
677
716
:short "Update our current expression for @('varname') to account for a new
679
718
((varname stringp "Variable we're considering.")
680
719
(x (and (vl-stmt-p x)
681
720
(vl-atomicstmt-p x)) "Statement that we're now encountering.")
682
(curr vl-maybe-expr-p "Expression we've built for varname up until now."))
722
"Expression we've built for varname up until now. (Initially an
723
appropriately sized X.)"))
683
724
:guard (vl-atomicstmt-cblock-p x)
684
:returns (expr? (and (vl-maybe-expr-p expr?)
685
(implies curr expr?))
725
:returns (expr? vl-expr-p
687
727
"New expression to assign to varname, after taking this
688
728
statement into account.")
691
731
;; Null statement has no effect
694
(if (equal varname (vl-idexpr->name (vl-assignstmt->lvalue x)))
695
;; Assign a new expression to this var
696
(vl-assignstmt->expr x)
697
;; Assignment to some other var doesn't affect var.
734
(b* (((unless (equal varname (vl-idexpr->name (vl-assignstmt->lvalue x))))
735
;; Assignment to some other var doesn't affect var.
737
;; Assign a new expression to this var
738
(expr (vl-assignstmt->expr x))
739
(finalwidth (vl-expr->finalwidth expr))
740
(- (or (posp finalwidth)
741
;; Should not happen because of stmttemps
742
(raise "No size on expression.")))
743
(wrapper (make-vl-nonatom :op :vl-concat
745
:finalwidth finalwidth
746
:finaltype :vl-unsigned)))
713
762
:short "Construct the expression for a single variable."
714
763
((varname stringp "Variable we're considering.")
715
764
(x vl-stmt-p "Statement we're descending through.")
716
(curr vl-maybe-expr-p "Expression we've built up for varname so far, if any."))
765
(curr vl-expr-p "Expression we've built up for varname so far."))
717
766
:guard (vl-stmt-cblock-p x)
718
767
:verify-guards nil
719
:returns (expr? (and (implies curr expr?)
720
(vl-maybe-expr-p expr?))
768
:returns (expr? vl-expr-p
722
770
"New expression for varname, if any")
723
771
:measure (vl-stmt-count x)
742
790
;; if (condition) [nothing] else var = false;
743
791
(vl-safe-qmark-expr x.condition curr false-expr)))
744
;; Possibility 1: this is something like:
792
;; Since we are initializing all variables to X, the only reason we
793
;; can be here is that we have something like:
746
795
;; if (condition) othervar = blah;
747
;; We don't care, just keep our current binding for var.
749
;; Possibility 2: this is something like:
751
;; if (condition) var = blah;
754
;; and we don't even have a binding for var yet. This is subtle
755
;; but fine. We don't care that this IF statement binds VAR, because
756
;; we know that VAR is ultimately bound on every path, so something
757
;; later has to overwrite it.
796
;; and we're encountering the IF. We don't care because this if
797
;; doesn't have anything to do with var.
760
800
((when (vl-blockstmt-p x))
767
807
(define vl-stmtlist-cblock-varexpr
768
808
((varname stringp "Variable we're considering.")
769
809
(x vl-stmtlist-p "Statement we're descending through.")
770
(curr vl-maybe-expr-p "Expression we've built up for varname so far, if any."))
810
(curr vl-expr-p "Expression we've built up for varname so far."))
771
811
:guard (vl-stmtlist-cblock-p x)
772
812
:returns (expr? (and (implies curr expr?)
773
813
(vl-maybe-expr-p expr?))
783
823
(verify-guards vl-stmt-cblock-varexpr))
785
(define vl-cblock-make-assign ((name stringp)
825
(define vl-cblock-make-assign ((name stringp)
786
826
(vars vl-vardecllist-p)
788
828
(ctx vl-always-p))
789
829
:returns (assigns vl-assignlist-p :hyp :fguard)
790
830
:guard (vl-stmt-cblock-p body)
791
(b* ((expr (vl-stmt-cblock-varexpr name body nil))
793
(raise "Failed to construct var expr for ~x0??" name))
794
(decl (vl-find-vardecl name vars))
831
(b* ((decl (vl-find-vardecl name vars))
796
833
(raise "Failed to find reg decl for ~x0??" name))
797
((vl-vardecl decl) decl)
798
834
((unless (and (vl-simplereg-p decl)
799
835
(vl-maybe-range-resolved-p (vl-simplereg->range decl))))
800
836
(raise "Variable decl too hard for ~x0??" name))
801
837
(size (vl-maybe-range-size (vl-simplereg->range decl)))
802
838
(type (if (vl-simplereg->signedp decl) :vl-signed :vl-unsigned))
840
;; Create an appropriately-sized X to initialize the variable with.
841
;; This variable will only matter if some branches of the IF do not
842
;; assign to this variable. This is unsigned to agree with the
843
;; concatenations around the expressions above.
844
(make-vl-atom :guts (make-vl-weirdint :origwidth size
845
:origtype :vl-unsigned
846
:bits (repeat size :vl-xval)
849
:finaltype :vl-unsigned))
850
(expr (vl-stmt-cblock-varexpr name body initial-x))
803
851
(lhs (vl-idexpr name size type))
804
852
(assign (make-vl-assign :lvalue lhs
908
955
;; Found blocks to convert. Convert them into assigns.
909
956
(delta (vl-starting-delta x))
910
(delta (change-vl-delta delta
957
(delta (change-vl-delta delta :assigns x.assigns))
913
958
((mv delta cvtregs) (vl-cblocks-synth cblocks x.vardecls delta))
914
;; The delta may have assigns, netdecls, and warnings for us.
959
;; The delta may have assigns, new vardecls, and new warnings for us.
915
960
((vl-delta delta) delta)
917
(non-regs (difference (mergesort cvtregs)
918
(mergesort (vl-vardecllist->names x.vardecls))))
920
;; Should be impossible
921
(raise "Trying to convert non-registers: ~x0.~%" non-regs)
962
((mv fixed-vardecls fixed-portdecls)
963
(vl-convert-regs cvtregs x.vardecls x.portdecls))
965
(final-vardecls (append-without-guard
969
;; Extra sanity check: final vardecls had better all be unique
970
((unless (uniquep (vl-vardecllist->names final-vardecls)))
971
(raise "Name clash when converting combinational blocks! ~x0."
972
(duplicated-members (vl-vardecllist->names final-vardecls)))
924
((mv vardecls-to-convert new-vardecls)
925
(vl-filter-vardecls cvtregs x.vardecls))
927
(new-netdecls (append (vl-always-convert-regs vardecls-to-convert)
929
975
(new-x (change-vl-module x
931
:netdecls new-netdecls
932
:vardecls new-vardecls
977
:vardecls final-vardecls
978
:portdecls fixed-portdecls
933
979
:assigns delta.assigns
934
980
:warnings delta.warnings)))