Hello to all, it is great that <@U016HSAA3RQ> has ...
# timing-closure
k
Hello to all, it is great that @User has created this channel due to numerous problems related to the timing. I have one issue, which is about multi cycle analysis of a circuit. In my design I have 2 clock enables running periodically at different rates. Until now I was not able to setup the tool (via constrains file). I was investigating how OpenSTA works and have made some test circuit (find attached the figure, RTL level model and GL model) and tried to constrain it using a TCL script. I got success manually setting the names of the flip-flops in the set_multicycle command:
s
You can set multicyle paths from clocks. Like set_multicycle_path -from [get_clocks x] -to [get_clocks y] -setup somevalue
k
Hi, do you refer to clock clock and clock enable signals ?
s
Clock, I mean the name of your clock while creating them using create_clock
By setting them the tool should see a multi cycle bewteen any sequential element operating from one clock to another.
k
yes I declare one clock create_clock -name clk -period 5 [get_ports clk]
Copy code
always@(posedge clk) begin
    if(rst ==1'b1) 
    begin
      X1 <= 3'b000;
      Yt <= 3'b000;
    end
    else if(en == 1) begin 
      X1 <= X_i;
      Yt[0] <=  X1[0] & X1[1];
      Yt[1] <=  X1[1] | X1[2];
      Yt[2] <=  X1[0] ^ X1[2];
    end
  end
as far as I understand the OpenSTA gives You setup and hold time estimation in reference to the clock
s
Something like this
20211028_174849.jpg
k
however in my design I have the "en" signal which appears every N cycles of the clock, so the launch and capture FF are actualized only if en ==1 so every N cycle. The multicycle command informs the OpenSTA that there exists a multicycle path. The problem I have is in fact related to the access to those variables to setup the command. my launch FF is X1, and the capture FF is Yt and I would like to setup the command using this names
ok, so I should create a clock which emulates my enable signal
Copy code
create_generated_clock -name en -source clk -divide_by 4  en
s
So the data path bewteen launch FF X1 and capture FF Yt has to be made multicyle right?
k
yes
s
Oh are there other single cycle paths in that clock
k
Copy code
set_multicycle_path 4 -setup  -from en -to clk
something like this ?
s
En signal arrives some in intervals of N cycles . I thought en was from another clock but it's from same clock. In your case you have give the reg name itself.
Setting multicycle from en to CLK wont do since en is not clocking any register elements in your design
k
ok, so I have tried mannually set the registers names using the names generated by yosys,
Copy code
set_multicycle_path 4 -setup  -from _33_ -to _45_
it works
s
Meanwhile without specifying the multicycle can you time the design and check the delay bewteen the x and y flipflop. If its less than the N x clock period your design is guaranteed to work functionally. For surety you have constrain using the name itself
k
however still You have to dig in the GL netlist to get those registers
s
Does the name changes every synthesis run?
k
have not checked that
the name appears as a "net"
get_net X1* gives this _b0959921f8550000_p_Net _20b0c028f8550000_p_Net _902db426f8550000_p_Net
s
Is it possible to do reg exp check like -from /yourmodule/*
k
hovewer the set_multicycle_path does not accept [get_net X1] it should be a [get_port X1], which returns warning that it can not be found
I was wonderg if is there any method to transform net to port or somehow get the information about the ports of the net
untill You do RCX extraction it should give you the same estimation of setup and hold
s
No idea on this one..
k
sorry, I have to go now, if You have any idea how to cope with that would be great to try it
I suppose there is a method because I doubt that the people doing STA dig in the GL netlist
s
I will check if there is any way to do this..
k
ok, taknks
I am looking for solution as well
s
Yes mostly we do reg Expression to get the port name and then do.
k
so the trick would be how to get port out of a net
s
Getting driver of that net. Else I have seen _reg being added extra to registers in the design to facilitate such operations.
k
Copy code
all_register
_f093691af8550000_p_Instance _b0977d1cf8550000_p_Instance _1020891ef8550000_p_Instance _20f79921f8550000_p_Instance _b0f79921f8550000_p_Instance _d038bb27f8550000_p_Instance
this is what I get when I call All_registers
Copy code
[get_ports -of_objects [get_net X1*]]
[{}]
it really confuses me because the X1 nets are connected to the launch flops
Copy code
sky130_fd_sc_hd__dfxtp_1 _32_ (
    .CLK(clk),
    .D(_00_),
    .Q(\X1[0] )
  );
  sky130_fd_sc_hd__dfxtp_1 _33_ (
    .CLK(clk),
    .D(_01_),
    .Q(\X1[1] )
  );
  sky130_fd_sc_hd__dfxtp_1 _34_ (
    .CLK(clk),
    .D(_02_),
    .Q(\X1[2] )
  );
and to other logic elements ie.
Copy code
sky130_fd_sc_hd__nand2_1 _23_ (
    .A(\X1[1] ),
    .B(\X1[0] ),
    .Y(_10_)
  );
the procedure could be like this: find ports related to the particular net and then verify which is FF (if any) and then use this FF in the multi cycle analysis
s
Yes from the clock port of launch flop to data in pin of capture like from dff/CLK to dff/D
k
agreed, however the confusion I have is about that command
Copy code
[get_ports -of_objects [get_net X1*]]
it returns empty list
and the X1 ports are connected to the launch flop ant to the logic between the flops
is there something wrong with those names
get_net X1* _b0959921f8550000_p_Net _20b0c028f8550000_p_Net _902db426f8550000_p_Net
s
X net connects to launch flop out its expected..
Are you able to check the netlist manually?
k
yes
Copy code
module TestSta(clk, rst, en, X_i, Y_o);
  wire _00_;
  wire _01_;
  wire _02_;
  wire _03_;
  wire _04_;
  wire _05_;
  wire _06_;
  wire _07_;
  wire _08_;
  wire _09_;
  wire _10_;
  wire _11_;
  wire _12_;
  wire _13_;
  wire _14_;
  wire _15_;
  wire \X1[0] ;
  wire \X1[1] ;
  wire \X1[2] ;
  input [2:0] X_i;
  output [2:0] Y_o;
  input clk;
  input en;
  input rst;
  sky130_fd_sc_hd__buf_6 _16_ (
    .A(en),
    .X(_06_)
  );
  sky130_fd_sc_hd__mux2i_1 _17_ (
    .A0(\X1[0] ),
    .A1(X_i[0]),
    .S(_06_),
    .Y(_07_)
  );
  sky130_fd_sc_hd__nor2_1 _18_ (
    .A(rst),
    .B(_07_),
    .Y(_00_)
  );
  sky130_fd_sc_hd__mux2i_1 _19_ (
    .A0(\X1[1] ),
    .A1(X_i[1]),
    .S(_06_),
    .Y(_08_)
  );
  sky130_fd_sc_hd__nor2_1 _20_ (
    .A(rst),
    .B(_08_),
    .Y(_01_)
  );
  sky130_fd_sc_hd__mux2i_1 _21_ (
    .A0(\X1[2] ),
    .A1(X_i[2]),
    .S(_06_),
    .Y(_09_)
  );
  sky130_fd_sc_hd__nor2_1 _22_ (
    .A(rst),
    .B(_09_),
    .Y(_02_)
  );
  sky130_fd_sc_hd__nand2_1 _23_ (
    .A(\X1[1] ),
    .B(\X1[0] ),
    .Y(_10_)
  );
  sky130_fd_sc_hd__nor2_1 _24_ (
    .A(_06_),
    .B(Y_o[0]),
    .Y(_11_)
  );
  sky130_fd_sc_hd__a211oi_1 _25_ (
    .A1(_06_),
    .A2(_10_),
    .B1(_11_),
    .C1(rst),
    .Y(_03_)
  );
  sky130_fd_sc_hd__nor2_1 _26_ (
    .A(\X1[1] ),
    .B(\X1[2] ),
    .Y(_12_)
  );
  sky130_fd_sc_hd__nor2_1 _27_ (
    .A(_06_),
    .B(Y_o[1]),
    .Y(_13_)
  );
  sky130_fd_sc_hd__a211oi_1 _28_ (
    .A1(_06_),
    .A2(_12_),
    .B1(_13_),
    .C1(rst),
    .Y(_04_)
  );
  sky130_fd_sc_hd__xnor2_1 _29_ (
    .A(\X1[0] ),
    .B(\X1[2] ),
    .Y(_14_)
  );
  sky130_fd_sc_hd__nor2_1 _30_ (
    .A(_06_),
    .B(Y_o[2]),
    .Y(_15_)
  );
  sky130_fd_sc_hd__a211oi_2 _31_ (
    .A1(_06_),
    .A2(_14_),
    .B1(_15_),
    .C1(rst),
    .Y(_05_)
  );
  sky130_fd_sc_hd__dfxtp_1 _32_ (
    .CLK(clk),
    .D(_00_),
    .Q(\X1[0] )
  );
  sky130_fd_sc_hd__dfxtp_1 _33_ (
    .CLK(clk),
    .D(_01_),
    .Q(\X1[1] )
  );
  sky130_fd_sc_hd__dfxtp_1 _34_ (
    .CLK(clk),
    .D(_02_),
    .Q(\X1[2] )
  );
  sky130_fd_sc_hd__dfxtp_1 _35_ (
    .CLK(clk),
    .D(_03_),
    .Q(Y_o[0])
  );
  sky130_fd_sc_hd__dfxtp_1 _36_ (
    .CLK(clk),
    .D(_04_),
    .Q(Y_o[1])
  );
  sky130_fd_sc_hd__dfxtp_1 _37_ (
    .CLK(clk),
    .D(_05_),
    .Q(Y_o[2])
  );
endmodule
s
Oh the command I am not sure. Also may I ask there seems be only a single gate bewteen X and Y flops. Even though the flops are enabled once in N cycles, you may need not set multicycle path. Usually if the delay is so high that it's not being met in single cycle then logic is changed to multicycle path.
k
The design I have published together with the issue I have is just for test, I wanted to make it simple just to visualize the problem and be able to get through the netlist manually. My objective is to figure out how the setup for multicycle works to use it in my target design which is way bigger.
the idea of the multicycle path and the command itself is pretty clear for me. The main issue is how can one setup the multicycle path using only the RTL code variables
s
I will give a try in my design if there is some way to get the flop name and the port
k
the one thing I have noticed looking for information that in PrimeTime of Synopsys the command all_registers returns the names of registers used in the GL netlist ad here it returns the registers instances using some internal representation
Copy code
all_register
_f093691af8550000_p_Instance _b0977d1cf8550000_p_Instance _1020891ef8550000_p_Instance _20f79921f8550000_p_Instance _b0f79921f8550000_p_Instance _d038bb27f8550000_p_Instance
would be great if You could give it a try
s
Also if from en port there are only multicycle Paths you may set set_multicycle_path -from en -to *
The -to option may be omitted also I think so
k
ok lest give it a try
Copy code
Startpoint: en (input port clocked by clk)
Endpoint: _37_ (rising edge-triggered flip-flop clocked by clk)
Path Group: clk
Path Type: min

  Delay    Time   Description
---------------------------------------------------------
   0.00    0.00   clock clk (rise edge)
   0.00    0.00   clock network delay (ideal)
   0.50    0.50 ^ input external delay
   0.01    0.51 ^ en (in)
   0.10    0.61 ^ _16_/X (sky130_fd_sc_hd__buf_6)
   0.05    0.66 v _31_/Y (sky130_fd_sc_hd__a211oi_2)
   0.00    0.66 v _37_/D (sky130_fd_sc_hd__dfxtp_1)
           0.66   data arrival time

  15.00   15.00   clock clk (rise edge)
   0.00   15.00   clock network delay (ideal)
   0.50   15.50   clock uncertainty
   0.00   15.50   clock reconvergence pessimism
          15.50 ^ _37_/CLK (sky130_fd_sc_hd__dfxtp_1)
  -0.03   15.47   library hold time
          15.47   data required time
---------------------------------------------------------
          15.47   data required time
          -0.66   data arrival time
---------------------------------------------------------
         -14.81   slack (VIOLATED)


Startpoint: _35_ (rising edge-triggered flip-flop clocked by clk)
Endpoint: Y_o[0] (output port clocked by clk)
Path Group: clk
Path Type: max

  Delay    Time   Description
---------------------------------------------------------
   0.00    0.00   clock clk (rise edge)
   0.00    0.00   clock network delay (ideal)
   0.00    0.00 ^ _35_/CLK (sky130_fd_sc_hd__dfxtp_1)
   0.42    0.42 ^ _35_/Q (sky130_fd_sc_hd__dfxtp_1)
   0.00    0.42 ^ Y_o[0] (out)
           0.42   data arrival time

   5.00    5.00   clock clk (rise edge)
   0.00    5.00   clock network delay (ideal)
  -0.50    4.50   clock uncertainty
   0.00    4.50   clock reconvergence pessimism
  -0.50    4.00   output external delay
           4.00   data required time
---------------------------------------------------------
           4.00   data required time
          -0.42   data arrival time
---------------------------------------------------------
           3.58   slack (MET)
so it starts on enable and then terminates in capture flop
this is the min path
the max path is from the capture flop to the output
the question is why it violates
s
Your clock rise edge at the launch flop is at 15ns. Actually the skew is 0.47 ns only and the min data delay is 0.66 so ur hold skew should be 0.66-0.47 = 0.19ns