Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extract Capacitor Arrary Generation to Earlier in the Flow #661

Open
2 of 3 tasks
stevenmburns opened this issue Apr 24, 2021 · 15 comments
Open
2 of 3 tasks

Extract Capacitor Arrary Generation to Earlier in the Flow #661

stevenmburns opened this issue Apr 24, 2021 · 15 comments
Assignees

Comments

@stevenmburns
Copy link
Collaborator

stevenmburns commented Apr 24, 2021

@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:

  • Understand the differences between the current instantiation model and the typical folded model used in primitives. It seems that the capacitor array template names can be associated with different instance names without the same layout (even bounding box) being generated. We need to work out what we want to do. This is what happens now when we run switched_capacitor_filter through the flow now with -n 10. The first two error messages show where capacitor templates are instantiated more than once. The remaining error messages shows that we are not following the folding model (each instantiation of a particular template has the same bounding box/layout.)
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')]
PnR.PnRDB.PnRdatabase._ReadLEF INFO : PnRDB-Info: reading LEF file <string>
align.pnr.build_pnr_model INFO : Finished reading contraint json file switched_capacitor_filter.pnr.const.json
align.pnr.build_pnr_model INFO : Finished reading contraint json file telescopic_ota.pnr.const.json
align.pnr.build_pnr_model INFO : Finished reading contraint json file CMC_S_PMOS.pnr.const.json
PnR.PnRDB.PnRdatabase.MergeLEFMapData INFO : merge LEF/map data on node switched_capacitor_filter
PnR.PnRDB.PnRdatabase.MergeLEFMapData INFO : merge LEF/map data on node telescopic_ota
PnR.PnRDB.PnRdatabase.MergeLEFMapData INFO : merge LEF/map data on node CMC_S_PMOS
align.pnr.toplevel INFO : Starting bottom-up placement on CMC_S_PMOS 2
PnR.placer.SeqPair.SetEnumerate INFO : Enumerated search
PnR.placer.Placer.PlacementCoreAspectRatio_ILP INFO : Exhausted all permutations of sequence pairs
align.pnr.toplevel WARNING : Placer did not provide numLayout (10 > 2) layouts
PnR.PnRDB.PnRdatabase.CheckinHierNode INFO : CheckinHierNode
PnR.PnRDB.PnRdatabase.CheckinHierNode INFO : CheckinHierNode
align.pnr.toplevel INFO : Starting bottom-up placement on telescopic_ota 1
PnR.PnRDB.PnRdatabase.CheckinHierNode INFO : CheckinHierNode
PnR.PnRDB.PnRdatabase.CheckinHierNode INFO : CheckinHierNode
PnR.PnRDB.PnRdatabase.CheckinHierNode INFO : CheckinHierNode
PnR.PnRDB.PnRdatabase.CheckinHierNode INFO : CheckinHierNode
PnR.PnRDB.PnRdatabase.CheckinHierNode INFO : CheckinHierNode
PnR.PnRDB.PnRdatabase.CheckinHierNode INFO : CheckinHierNode
PnR.PnRDB.PnRdatabase.CheckinHierNode INFO : CheckinHierNode
PnR.PnRDB.PnRdatabase.CheckinHierNode INFO : CheckinHierNode
PnR.PnRDB.PnRdatabase.CheckinHierNode INFO : CheckinHierNode
PnR.PnRDB.PnRdatabase.CheckinHierNode INFO : CheckinHierNode
align.pnr.toplevel INFO : Starting bottom-up placement on switched_capacitor_filter 0
PnR.cap_placer.Placer_Router_Cap.Common_centroid_capacitor_aspect_ratio INFO : CC Capacitor Placement and Router : switched_capacitor_filter c0_c4
PnR.cap_placer.Placer_Router_Cap.Common_centroid_capacitor_aspect_ratio INFO : CC Capacitor Placement and Router : switched_capacitor_filter c5_c2
PnR.cap_placer.Placer_Router_Cap.Common_centroid_capacitor_aspect_ratio INFO : CC Capacitor Placement and Router : switched_capacitor_filter c6_c3
PnR.cap_placer.Placer_Router_Cap.Common_centroid_capacitor_aspect_ratio INFO : CC Capacitor Placement and Router : switched_capacitor_filter c7_c1
PnR.cap_placer.Placer_Router_Cap.Common_centroid_capacitor_aspect_ratio INFO : CC Capacitor Placement and Router : switched_capacitor_filter c9_c8
PnR.PnRDB.PnRdatabase.CheckinHierNode INFO : CheckinHierNode
PnR.PnRDB.PnRdatabase.CheckinHierNode INFO : CheckinHierNode
PnR.PnRDB.PnRdatabase.CheckinHierNode INFO : CheckinHierNode
PnR.PnRDB.PnRdatabase.CheckinHierNode INFO : CheckinHierNode
PnR.PnRDB.PnRdatabase.CheckinHierNode INFO : CheckinHierNode
PnR.PnRDB.PnRdatabase.CheckinHierNode INFO : CheckinHierNode
PnR.PnRDB.PnRdatabase.CheckinHierNode INFO : CheckinHierNode
PnR.PnRDB.PnRdatabase.CheckinHierNode INFO : CheckinHierNode
PnR.PnRDB.PnRdatabase.CheckinHierNode INFO : CheckinHierNode
PnR.PnRDB.PnRdatabase.CheckinHierNode INFO : CheckinHierNode
align.pnr.render_placement ERROR : Different leaf bboxes for Cap_cc_5_5: [(0, 0, 24960, 20328), (0, 0, 19200, 26208), (0, 0, 24960, 20328)]
align.pnr.render_placement INFO : Drawing switched_capacitor_filter_0...
align.pnr.render_placement ERROR : Different leaf bboxes for Cap_cc_5_5: [(0, 0, 24960, 20328), (0, 0, 19200, 26208), (0, 0, 24960, 20328)]
align.pnr.render_placement INFO : Drawing switched_capacitor_filter_1...
align.pnr.render_placement ERROR : Different leaf bboxes for Cap_cc_5_5: [(0, 0, 24960, 20328), (0, 0, 19200, 26208), (0, 0, 24960, 20328)]
align.pnr.render_placement INFO : Drawing switched_capacitor_filter_2...
align.pnr.render_placement ERROR : Different leaf bboxes for Cap_cc_5_5: [(0, 0, 24960, 20328), (0, 0, 19200, 26208), (0, 0, 24960, 20328)]
align.pnr.render_placement INFO : Drawing switched_capacitor_filter_3...
align.pnr.render_placement ERROR : Different leaf bboxes for Cap_cc_5_5: [(0, 0, 24960, 20328), (0, 0, 19200, 26208), (0, 0, 24960, 20328)]
align.pnr.render_placement INFO : Drawing switched_capacitor_filter_4...
align.pnr.render_placement ERROR : Different leaf bboxes for Cap_cc_5_5: [(0, 0, 24960, 20328), (0, 0, 19200, 26208), (0, 0, 24960, 20328)]
align.pnr.render_placement INFO : Drawing switched_capacitor_filter_5...
align.pnr.render_placement ERROR : Different leaf bboxes for Cap_cc_5_5: [(0, 0, 24960, 20328), (0, 0, 19200, 26208), (0, 0, 24960, 20328)]
align.pnr.render_placement INFO : Drawing switched_capacitor_filter_6...
align.pnr.render_placement ERROR : Different leaf bboxes for Cap_cc_5_5: [(0, 0, 24960, 20328), (0, 0, 19200, 26208), (0, 0, 24960, 20328)]
align.pnr.render_placement INFO : Drawing switched_capacitor_filter_7...
align.pnr.render_placement ERROR : Different leaf bboxes for Cap_cc_5_5: [(0, 0, 24960, 20328), (0, 0, 19200, 26208), (0, 0, 24960, 20328)]
align.pnr.render_placement INFO : Drawing switched_capacitor_filter_8...
align.pnr.render_placement INFO : Drawing switched_capacitor_filter_9...
  • Once we figure out the semantics of these placement variants (and probably routing variants as well), we will want normal primitives to have variants as well (different aspect ratios.)
  • Then we can move the CC code to before the place and route loop

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

@854768750
Copy link
Collaborator

854768750 commented Apr 26, 2021

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
Copy link
Collaborator Author

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
Copy link
Collaborator Author

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
Copy link
Collaborator Author

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
Copy link
Collaborator

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
Copy link
Collaborator Author

stevenmburns commented Apr 26, 2021

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
Copy link
Collaborator

854768750 commented Apr 27, 2021

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
Copy link
Collaborator Author

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
Copy link
Collaborator

854768750 commented Apr 27, 2021

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
Copy link
Collaborator

(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
Copy link
Collaborator

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

kkunal1408 pushed a commit that referenced this issue Apr 27, 2021
@kkunal1408
Copy link
Collaborator

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
Copy link
Collaborator Author

@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
Copy link
Collaborator Author

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

@parijatm
Copy link
Collaborator

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants