ALIGN-analoglayout / ALIGN-public

BSD 3-Clause "New" or "Revised" License
260 stars 66 forks source link

Extract Capacitor Arrary Generation to Earlier in the Flow #661

Open stevenmburns opened 3 years ago

stevenmburns commented 3 years ago

@kkunal1408 @parijatm @soneryaldiz @Lastdayends This issue it to track progress on moving the capacitor array generation from the pnr phase to the primitive phase. Here are some things to do:

We could do some simple things first like make sure that we have different template names when we want to allow different layouts.

854768750 commented 3 years ago

I think this is special case in capacitor. We may need another term "gdsFile" to identify different instances of capacitors. 3_times_4 4_times_3 The two capacitors have the same "master", but different "gdsFile"

stevenmburns commented 3 years ago

I corrected the error message in the initial description. The issue is as you said is that there are several different usages of the same capacitor template name. Which do we want to be identical in layout and which are we allowed to make different.

align.pnr.main ERROR : CC Capacitor with template_name Cap_cc_3_3 instantiated more than once: [('switched_capacitor_filter', 'c5_c2'), ('switched_capacitor_filter', 'c7_c1')]
align.pnr.main ERROR : CC Capacitor with template_name Cap_cc_5_5 instantiated more than once: [('switched_capacitor_filter', 'c0_c4'), ('switched_capacitor_filter', 'c6_c3'), ('switched_capacitor_filter', 'c9_c8')]
stevenmburns commented 3 years ago

Here is the verilog for the switched capacitor filter. Which of the Cap_cc_5_5 capacitor arrays should be identical? How about the Cap_cc_33_3 capacitor arrays?

module switched_capacitor_filter ( agnd, id, vinn, vinp, voutn, voutp );
input agnd, id, vinn, vinp, voutn, voutp;

Switch_NMOS_B_nfin12_n12_X1_Y1_RVT m0 ( .B(vss), .D(voutn), .G(phi1), .S(net67) );
Switch_NMOS_B_nfin12_n12_X1_Y1_RVT m7 ( .B(vss), .D(net66), .G(phi1), .S(net63) );
Switch_NMOS_B_nfin12_n12_X1_Y1_RVT m6 ( .B(vss), .D(net72), .G(phi1), .S(vinn) );
Switch_NMOS_B_nfin12_n12_X1_Y1_RVT m3 ( .B(vss), .D(agnd), .G(phi2), .S(net67) );
Switch_NMOS_B_nfin12_n12_X1_Y1_RVT m5 ( .B(vss), .D(agnd), .G(phi2), .S(net63) );
Switch_NMOS_B_nfin12_n12_X1_Y1_RVT m4 ( .B(vss), .D(net72), .G(phi2), .S(agnd) );
Switch_NMOS_B_nfin12_n12_X1_Y1_RVT m8 ( .B(vss), .D(net60), .G(phi2), .S(agnd) );
Switch_NMOS_B_nfin12_n12_X1_Y1_RVT m11 ( .B(vss), .D(agnd), .G(phi2), .S(net68) );
Switch_NMOS_B_nfin12_n12_X1_Y1_RVT m9 ( .B(vss), .D(agnd), .G(phi2), .S(net62) );
Switch_NMOS_B_nfin12_n12_X1_Y1_RVT m10 ( .B(vss), .D(net64), .G(phi1), .S(net62) );
Switch_NMOS_B_nfin12_n12_X1_Y1_RVT m12 ( .B(vss), .D(net60), .G(phi1), .S(vinp) );
Switch_NMOS_B_nfin12_n12_X1_Y1_RVT m14 ( .B(vss), .D(voutp), .G(phi1), .S(net68) );
telescopic_ota xi0 ( .d1(id), .vbiasn(vbiasn), .vbiasp1(vbiasp1), .vbiasp2(vbiasp2), .vinn(net64), .vinp(net66), .voutn(voutn), .voutp(voutp) );
Cap_cc_5_5 c0_c4 ( .MINUS0(net63), .MINUS1(net60), .PLUS0(net72), .PLUS1(net62) );
Cap_cc_3_3 c5_c2 ( .MINUS0(vinn), .MINUS1(net66), .PLUS0(net64), .PLUS1(vinp) );
Cap_cc_5_5 c6_c3 ( .MINUS0(net64), .MINUS1(voutn), .PLUS0(voutp), .PLUS1(net66) );
Cap_cc_3_3 c7_c1 ( .MINUS0(net68), .MINUS1(net67), .PLUS0(net62), .PLUS1(net63) );
Cap_cc_5_5 c9_c8 ( .MINUS0(vss), .MINUS1(voutn), .PLUS0(voutp), .PLUS1(vss) );

endmodule
module telescopic_ota ( d1, vbiasn, vbiasp1, vbiasp2, vinn, vinp, voutn, voutp );
input d1, vbiasn, vbiasp1, vbiasp2, vinn, vinp, voutn, voutp;

DCL_NMOS_nfin24_n12_X2_Y1_RVT m5 ( .D(d1), .S(vss) );
Switch_NMOS_nfin36_n12_X3_Y1_RVT m4 ( .D(net10), .G(d1), .S(vss) );
CMC_S_NMOS_B_nfin36_n12_X3_Y1_RVT m9_m8 ( .B(vss), .DA(voutn), .DB(voutp), .G(vbiasn), .SA(net8), .SB(net014) );
CMC_PMOS_nfin12_n12_X1_Y1_RVT m2_m1 ( .DA(net012), .DB(net06), .G(vbiasp1), .S(vdd) );
CMC_S_PMOS m7_m6 ( .DA(voutp), .DB(voutn), .G(vbiasp2) );
DP_NMOS_B_nfin72_n12_X6_Y1_RVT m3_m0 ( .B(vss), .DA(net014), .DB(net8), .GA(vinn), .GB(vinp), .S(net10) );

endmodule
module CMC_S_PMOS ( DA, DB, G );
input DA, DB, G;

Switch_PMOS_nfin24_n12_X2_Y1_RVT M0 ( .D(DA), .G(G), .S(SA) );
Switch_PMOS_nfin24_n12_X2_Y1_RVT M1 ( .D(DB), .G(G), .S(SB) );

endmodule

`celldefine
module global_power;
supply0 vss;
supply1 vdd;
endmodule
`endcelldefine
stevenmburns commented 3 years ago

The constraints look like this. We are only specifying constraints on two of the instances.

[
    {
        "constraint": "GroupCaps",
        "name": "c1_c3",
        "instances": ["c1", "c3"],
        "unit_cap": "Cap_12f",
        "num_units": [3, 5],
        "dummy": false
    },
    {
        "constraint": "GroupCaps",
        "name": "c7_c6",
        "instances": ["c7","c6"],
        "unit_cap": "Cap_12f",
        "num_units": [3, 5],
        "dummy": false
    }
]
854768750 commented 3 years ago

cap_cc is generated here https://github.com/ALIGN-analoglayout/ALIGN-public/blob/master/align/pnr/toplevel.py#L187. For the same master name, there are multiple different gdsfile. And the placer chooses the best gdsfile. For the first of the 10 layouts, c0_c4 and c9_c8 are the same. c6_c3 is different. c5_c2 and c7_c1 are different.

stevenmburns commented 3 years ago

Adding @soneryaldiz @parijatm @arvuce22. @854768750 Yes, I think I see that is how the flow is working now. What do we want it to do? Why do we only specify a constraint for some of the capacitor pairs? Why do they seem to be ignored? (c1 and c3 are not grouped together in the verilog netlist.) How do we specify that we want two capacitor pairs to have the same layout if not by giving them the same instance name? How should we generalize this to other primitives where we might want the placer to chose between multiple different aspect ratios of a particular primitive? Do we use master name for that? Or something else. Do we need a mapping between a given master name and its possible layouts?

854768750 commented 3 years ago

Multiple different aspect ratios of a particular primitive use the same master name, but use different "gdsfile". The mapping is in switched_capacitor_filter.map Currently, it is one to one mapping because a particular primitive has only one aspect ratio. It could also be one to many mapping if there are multiple aspect ratios (this may need modification to the code).

stevenmburns commented 3 years ago

What should this look like in the map file. It is only a list of pairs. Can we have

foo foo-aspect-3-5.gds
foo foo-aspect-5-3.gds

Is that how we do the one-to-many mapping?

854768750 commented 3 years ago

Yes. It could be like this. After the map file is changed to this format, please @854768750 in any pull request so that I can make some modifications to the code.

854768750 commented 3 years ago

(c1 and c3 are not grouped together in the verilog netlist.)

I also find that in the constraints, there are c1_c3 and c6_c3. So c3 is in two groups. However, c1_c3 seems not being enabled. c3 is grouped with c6.

kkunal1408 commented 3 years ago

The constraints look wrong right now. There should be only one grouping of c3. I will fix this.

kkunal1408 commented 3 years ago

Now, c3 is part of only one group in the constraint and there is a symmetry constraint between c1_c3 and c7_c6, implying both blocks have should have the same master (ideally they should be mirror images). @stevenmburns @854768750 The PnR error still exists.

stevenmburns commented 3 years ago

@kkunal1408 @parijatm Thanks for fixing this. It seems that we want c1_c3 to have the same layout as c7_c6 but we don't care if c0_c4 has the same layout as c8_c9. Right now the placer is free to chose different aspect ratios for all the capacitors, guided possibly by its understanding of Symmetry constraints, etc. We need to check that it does the right thing. When we bring the results of placement back into our folded model, our representation forces all instances with the same template name to have identical bounding boxes and layout. This will force c0_c4 to have the same layout as c8_c9 even if we don't care. So we are going to have to specify and check this differently. One way is introduce a different template name if you want to allow a different implementation. So in this case 'Cap_cc_5_5_0' and 'Cap_cc_5_5_1' for instances c0_c4 and c8_c9 respectively. We still have the same single template name Cap_cc_3_5 for instances c1_c3 and c7_c6 . Then we need the PnR flow to respect choosing the same layout for the same template name. I guess this can be checked by asserting if they are different.

We could also just make all the template names unique and force the checker to ensure our particular sameness constraints are satisfied. Or maybe get rid of the concept of template name (maybe replace it with function_name, or abstract_name or class_name) because unique names do not provide a lot of value. We do need to specify which variants will be allowed to implement a particular instance.

Hierarchy also needs to be considered. We really want two instances of a hierarchical block to have the same internal instance layouts. The "make all the template names unique" approach above should still enforce this.

Here are the capacitor instances from the fixed switch_capacitor_filter

...
        { "template_name": "Cap_cc_3_5", "instance_name": "c1_c3", "fa_map": [ ...] },
        { "template_name": "Cap_cc_3_5", "instance_name": "c7_c6", "fa_map": [ ...] },
        { "template_name": "Cap_cc_5_5", "instance_name": "c0_c4", "fa_map": [ ...] },
        { "template_name": "Cap_cc_3_3", "instance_name": "c2_c5", "fa_map": [ ...] },
        { "template_name": "Cap_cc_5_5", "instance_name": "c8_c9", "fa_map": [ ...] }
...
stevenmburns commented 3 years ago

First two addressed in #671 We will work on the last one in a new PR.

parijatm commented 2 years ago

@stevenmburns will help with system level integration once the capacitor generator is implemented in Python.