Hi all, I'm attempting to use make a blackbox out ...
# openlane
j
Hi all, I'm attempting to use make a blackbox out of a custom made analog circuit that has multiple circuit blocks within it. I have drawn the gds in klayout and use magic to read the gds layout and generate the lef file. When I ran flow.tcl, I get stuck in the step: "running XOR on the layout using Klayout" (step 38 for me). I used
lef write bitfour_EESPFAL -tech
to generate the lef file in magic. Please tell me if I'm missing a step or my setup config is false. Any help is appreciated.
m
@JC the xor step here is comparing the klayout generated gds to the gds generated from magic. The expectation is that they are the same. Can you open both these files (klayout for both is fine) and see where they differ?
Copy code
Reading /openlane/designs/blackbox_test_2/runs/test/results/signoff/blackbox_test_2.gds ..
Reading /openlane/designs/blackbox_test_2/runs/test/results/signoff/blackbox_test_2.klayout.gds ..
It may be that you have saved your lef version of the magic file with a
.mag
extension instead of
.maglef
.
j
I will check those two files and report back in a bit. For the lef file in magic, am I suppose to do `save bitfour_EESPAL.maglef'?
m
@Tim Edwards?
t
There is no extension
.maglef
. A "maglef" file is simply an abstract view of a cell.
j
In the first picture it looks like the blackbox_test_2.gds shows the blackbox custom circuit is scaled down significantly but the die area of 300umx300um is achieved. For the second picture, the blackbox_test_2.klayout.gds shows the custom circuit to be the dimensions I'm expecting (49.86um x 77.68um) but the die area is 5 times the size. I've saved the .gds file in klayout with database unit of 0.005um. Is that wildly false? Regarding the decaps that have populated the layout, I understand openlane is filling up the empty die area. What would be the recommended step to not have that many decaps or buffers?
m
You might try disabling
RUN_TAP_DECAP_INSERTION
See https://openlane.readthedocs.io/en/latest/reference/configuration.html Don’t know about the size discrepancies.
j
Hi @Mitch Bailey, this time I used Magic to save the gds file that was originally generated from Klayout. ./flow.tcl clears step 38 with the XOR part. What would the reason behind the gds saved by using Magic make the size discrepancy not happen while Klayout's gds does? Now the next issue is ./flow.tcl lvs with the PWR and GND pins... It seems like it is not able to find it? Is there a setting I need to set in the config file?
m
FP_PDN_MACRO_HOOKS
needs to be set to connect macros to the power grid.
What would the reason behind the gds saved by using Magic make the size discrepancy not happen while Klayout’s gds does?
@Tim Edwards any ideas?
j
I have a question regarding `FP_PDN_MACRO_HOOKS.`The circuit I'm blackboxing is adiabatic in nature and it uses a four phase power clock. We are planning to use external power clock by using the GPIO pins. To my understanding the
FP_PDN_MACRO_HOOKS
requires the vdd gnd to be in pairs. What would be the way to tell the PDN_MACRO_HOOKS to make the GPIO pins as power clock pins?
m
I think you can specify the same macro multiple times if it has multiple power supplies. See this discussion.
j
I tried the following for the FP_PDN_MACRO_HOOKS. `"FP_PDN_MACRO_HOOKS": "submodule.bitfour_EESPFAL0 CLK[0] GND CLK[0] GND, submodule.bitfour_EESPFAL0 CLK[1] GND CLK[1] GND, submodule.bitfour_EESPFAL0 CLK[2] GND CLK[2] GND, submodule.bitfour_EESPFAL0 CLK[3] GND CLK[3] GND",`the error occurs in Running Tap/Decap Insertion where it couldn't find CLK[3] and GND. Maybe my issue is I have named the power clocks CLK[0]... CLK[3] and the ground as GND? Should I be invoking the gpio pin names to make them connect?
m
@JC I don’t know that the macro connector can handle non-paired power connections (ie. multiple power but only one ground). With adiabatic circuits, how are standard cell rows handled? I imagine the auto placement tool is assuming standard powered cells rows and wants to place tap/decap cells there. If only the clock circuit is adiabatic, you might be able to fool the router by adding a dummy power terminal in the macro layout. The CLK[*] should route as standard signals.
j
The adiabatic circuit is the only one that will be using the trapezoidal clock wave to power its circuits. Currently we are running flow.tcl from the main OpenLane github folder, and I assume it is using caravel_user_project as the target(?). The project goal is to make a one round PRESENT80 encryption and is mixed signal in nature, we are planning to use caravel_user_project_analog to wrap them together. The main encryption circuits and its traditional CMOS counterpart have been laid out. The next step is to use OpenLane to simplify the routing from caravel chip to the circuits. Regarding the standard cell rows, we are still debating on where to place them. To my understanding, the adiabatic circuits might interfere with the traditional circuits and we were advised to place them far from each other. Our current goal is to understand the quirks of making a blackbox, implement them on the complete versions, and then to all the other relevant digital circuits to interface with the caravel chip. I will try your suggestion of a dummy power pin and report back. One quick question I have is should I be worried that ./flow.tcl is not making it in user_project_analog's openlane folder?
m
The
Makefile
in the
caravel_user_project_analog
has targets that run the openroad
flow.tcl
script. I don’t think it is necessary (or advised?) to run the
flow.tcl
script directly, but I may be mistaken. “Normal” operation is to create a directory in the
caravel_user_project_analog/openlane
directory for each block that you want to synthesize with openlane. Each directory will have it’s own
config.json
file with the parameters necessary for synthesis. The top level will be
user_analog_project_wrapper
. Unfortunately, it looks like the current
caravel_user_project_analog/openlane
directory does not include any default blocks. Maybe reference
caravel_user_project/openlane
directories for samples. With the block directories and config.json files in place, just run
make <block>
in the
caravel_user_project_analog
directory to synthesize each design block with
flow.tcl
. Remember, you need to start at the lower blocks and re-synthesize all the parent blocks anytime a sub block is changed.
j
I will refer to that when the time comes. I've made a dummy power pin called VDD_Dummy in the layout. I have the following added to the config.json but received an error about no regex match found. It seems to be able to find the dummy pin.
"VDD_NETS":"VDD_Dummy",
"GND_NETS":"GND",
"FP_PDN_MACRO_HOOKS": "submodule.bitfour_EESPFAL0 VDD_Dummy GND VDD_Dummy GND",
m
Do you have
VDD_Dummy
in the top level verilog? Since the macro does not have a connection to
VDD
, you might try adding a floating
VDD
pin (instead of
VDD_Dummy
). Then connect your top level
VDD
to this floating pin.
Copy code
FP_PDN_MACRO_HOOKS": "submodule.bitfour_EESPFAL0 VDD GND VDD GND",
j
I have added VDD pin into blackbox_test_2.v (current top level). But I'm still having the same error for generating PDN. Am I still missing something?
m
Aren’t you missing a ground connection too?
j
I've updated blackbox_test_2.v to have the gnd connection, however I'm still receiving the same error.
m
@JC Sorry for any confusion. I’m not exactly sure how the macro power connections work, but with rtl, I think the power connections aren’t used during synthesis. They’re wrapped in a conditional macro like this. (See other openlane examples)
Copy code
user_proj_example mprj (
`ifdef USE_POWER_PINS
        .vccd1(vccd1),  // User area 1 1.8V power
        .vssd1(vssd1),  // User area 1 digital ground
`endif
Since they’re not specified during synthesis, the
FP_PDN_MACRO_HOOKS
is used for power routing. Can you try something like
Copy code
module blackbox_test_2(
	input [BIT_SIZE-1:0] clk_top,
	input [BIT_SIZE-1:0] dis_top,
	input [BIT_SIZE-1:0] x_top,
	input [BIT_SIZE-1:0] x_bar_top,
	input [BIT_SIZE-1:0] k_top,
	input [BIT_SIZE-1:0] k_bar_top,

	output [BIT_SIZE-1:0] s_top,
	output [BIT_SIZE-1:0] s_bar_top,
`ifdef USE_POWER_PINS	
	inout VDD,
	inout GND
`endif
);

	parameter BIT_SIZE = 4;

bitfour_EESPFAL #(BIT_SIZE) lane0(
	.s(s_top[3:0]),
	.s_bar(s_bar_top[3:0]),
	.x(x_top[3:0]),
	.x_bar(x_bar_top[3:0]),
	.k(k_top[3:0]),
	.k_bar(k_bar_top[3:0]),
	.CLK(clk_top[3:0]),
	.Dis(dis_top[3:0]),
	
`ifdef USE_POWER_PINS	
	.VDD(VDD), //Floating VDD pin to trick OpenLane
	.GND(GND)
`endif
);
I’ve changed the
VDD_Dummy
and
GND_Dummy
nets to
VDD
and
GND
to match the
FP_PDN_MACRO_HOOKS
settings. You want an actual
GND
connection, right?
j
Thanks @Mitch Bailey, I will try out the fix. As for the
GND
connection, we want to use the GPIO pins so we can have individual external GND and not through the caravel's GND. We want to compare the instantaneous power and functionality of Adiabatic circuit against its traditional digital circuit counterpart. Please correct me if there is a better or correct way to do this.
m
Without any extra layers, all psubstrate connections are “shorted” through the common substrate. The substrate resistance is much larger than normal wiring and often these shorts are ignored by creating virtual psubstrate areas (for sky130 it’s layer
81/53
) that do not connect during extraction. If you truly want to separate the psubstrate regions, normally you’d can place your macro in a deep nwell region with a nwell guard ring surrounding it. However, while this does give you an isolated pwell region, it also shorts all the nwells in the region to the same node, which is not what you want. Would it be possible to separate the pwell regions from the nwell regions by putting only the pwell inside deep nwell? It will probably be a larger circuit than what you have now. You’d tie the deep nwell to a true VDD.
j
Gotcha. The idea is we can use deep nwell to create isolated circuit between the adiabatic and its digital counterpart, but the price is area. With the fix above I'm still getting same error. I tried to stick 'ifdef use_power_pins in the blackbox but it still gives the same error as shown in the picture.
m
Maybe it’s the name of the module. Can you find the actual instance names in the synthesized verilog? Currently, you’re
config.json
file has
Copy code
"FP_PDN_MACRO_HOOKS": "submodule.bitfour_EESPFAL0 VDD GND VDD GND"
but I’m guessing the synthesized verilog has 4 individual macros named something like
Copy code
lane0[0]
lane0[1]
lane0[2]
lane0[3]
If this is the case, you want this
Copy code
"FP_PDN_MACRO_HOOKS": [
"lane0[0] VDD GND VDD GND,",
"lane0[1] VDD GND VDD GND,",
"lane0[2] VDD GND VDD GND,",
"lane0[3] VDD GND VDD GND,"
]
Note the “extra”
,
before the closing
"
.
j
I tried
lane0
, getting the same error. And I've also tried with`submodule.bitfour_EESPFAL0`and getting the same error as well.
m
Can you find the actual instance names in the synthesized verilog?
j
Does it belong to one of these? I'm not certain with what I'm looking for... I have included the ./flow run under the test.tar.xz the first two files are found in /test/results/synthesis the .nl.v and second verilog file are found in /test/results/final/verilog/gl
m
It doesn’t look like it’s synthesizing 4 instances of
bitfour_EESPFAL
. Does anyone know if yosys can synthesize parameterized instances like this
Copy code
parameter BIT_SIZE = 4;

bitfour_EESPFAL #(BIT_SIZE) lane0(
and if it can, what are the resulting 4 instance names.
l
I don't know if yosys supports this syntax, but alternatively one could use a generate for loop. I used one to instantiate multiple OpenRAM blocks in OpenLane: https://github.com/The-OpenROAD-Project/OpenLane/issues/1600
👍 1
j
@Leo Moser thank you for posting that. However, I do not exactly follow. Am I suppose to perform the following in config.json:
"FP_PDN_MACRO_HOOKS": ["lane\\\\[\\\\0\\\\]\\.bitfour_EESPFAL0 VDD GND VDD GND,","lane\\\\[\\\\1\\\\]\\.bitfour_EESPFAL0 VDD GND VDD GND,","lane\\\\[\\\\2\\\\]\\.bitfour_EESPFAL0 VDD GND VDD GND,","lane\\\\[\\\\3\\\\]\\.bitfour_EESPFAL0 VDD GND VDD GND,", "bitfour_EESPFAL0 VDD GND VDD GND"],
? I did that but still getting the same error. Openlane's saying its reading 3-initial_fp.sdc as shown in the log file but I don't get what needs to be done. I know we want to package the blackbox circuit as is, have openlane connect to the pins defined in the blackbox model. For this we want the GND to be connected to a GPIO pin, trapezoidal wave (CLK) and Discharge (Dis) signals to be connected via gpio pins.
Please correct me if the following graphic doesn't represent what openlane would do.
m
The instance names in the
FP_PDN_MACRO_HOOKS
variables need to match the names in the synthesized verilog. Can you try this variable with this rtl which uses explicit declarations?
Copy code
"FP_PDN_MACRO_HOOKS": ["lane0 VDD GND VDD GND,","lane1 VDD GND VDD GND,","lane2 VDD GND VDD GND,","lane3 VDD GND VDD GND,", "bitfour_EESPFAL0 VDD GND VDD GND"],
Verilog
Copy code
module blackbox_test_2(
	input [BIT_SIZE-1:0] clk_top,
	input [BIT_SIZE-1:0] dis_top,
	input [BIT_SIZE-1:0] x_top,
	input [BIT_SIZE-1:0] x_bar_top,
	input [BIT_SIZE-1:0] k_top,
	input [BIT_SIZE-1:0] k_bar_top,

	output [BIT_SIZE-1:0] s_top,
	output [BIT_SIZE-1:0] s_bar_top,
`ifdef USE_POWER_PINS	
	inout VDD,
	inout GND
`endif
);

bitfour_EESPFAL lane0 (
	.s(s_top[3:0]),
	.s_bar(s_bar_top[3:0]),
	.x(x_top[3:0]),
	.x_bar(x_bar_top[3:0]),
	.k(k_top[3:0]),
	.k_bar(k_bar_top[3:0]),
	.CLK(clk_top[3:0]),
	.Dis(dis_top[3:0]),
	
`ifdef USE_POWER_PINS	
	.VDD(VDD), //Floating VDD pin to trick OpenLane
	.GND(GND)
`endif
);

bitfour_EESPFAL lane1 (
	.s(s_top[3:0]),
	.s_bar(s_bar_top[3:0]),
	.x(x_top[3:0]),
	.x_bar(x_bar_top[3:0]),
	.k(k_top[3:0]),
	.k_bar(k_bar_top[3:0]),
	.CLK(clk_top[3:0]),
	.Dis(dis_top[3:0]),
	
`ifdef USE_POWER_PINS	
	.VDD(VDD), //Floating VDD pin to trick OpenLane
	.GND(GND)
`endif
);

bitfour_EESPFAL lane2 (
	.s(s_top[3:0]),
	.s_bar(s_bar_top[3:0]),
	.x(x_top[3:0]),
	.x_bar(x_bar_top[3:0]),
	.k(k_top[3:0]),
	.k_bar(k_bar_top[3:0]),
	.CLK(clk_top[3:0]),
	.Dis(dis_top[3:0]),
	
`ifdef USE_POWER_PINS	
	.VDD(VDD), //Floating VDD pin to trick OpenLane
	.GND(GND)
`endif
);

bitfour_EESPFAL lane3 (
	.s(s_top[3:0]),
	.s_bar(s_bar_top[3:0]),
	.x(x_top[3:0]),
	.x_bar(x_bar_top[3:0]),
	.k(k_top[3:0]),
	.k_bar(k_bar_top[3:0]),
	.CLK(clk_top[3:0]),
	.Dis(dis_top[3:0]),
	
`ifdef USE_POWER_PINS	
	.VDD(VDD), //Floating VDD pin to trick OpenLane
	.GND(GND)
`endif
);
j
I tried the code above, but got a couple linter errors. I've added ``ifdef USE_POWER_PINS` in the bitfour_EESPFAL.bb.v. Linter is warning about "__pinNUmber9", where do I find that? Is this a yosys thing?
m
Looks like the position of the
ifdef
causes the error. Try putting it first.
Copy code
module blackbox_test_2(
`ifdef USE_POWER_PINS	
	inout VDD,
	inout GND,
`endif
	input [BIT_SIZE-1:0] clk_top,
	input [BIT_SIZE-1:0] dis_top,
	input [BIT_SIZE-1:0] x_top,
	input [BIT_SIZE-1:0] x_bar_top,
	input [BIT_SIZE-1:0] k_top,
	input [BIT_SIZE-1:0] k_bar_top,

	output [BIT_SIZE-1:0] s_top,
	output [BIT_SIZE-1:0] s_bar_top
);

bitfour_EESPFAL lane0 (
`ifdef USE_POWER_PINS	
	.VDD(VDD), //Floating VDD pin to trick OpenLane
	.GND(GND),
`endif
	.s(s_top[3:0]),
	.s_bar(s_bar_top[3:0]),
	.x(x_top[3:0]),
	.x_bar(x_bar_top[3:0]),
	.k(k_top[3:0]),
	.k_bar(k_bar_top[3:0]),
	.CLK(clk_top[3:0]),
	.Dis(dis_top[3:0])
);

bitfour_EESPFAL lane1 (
`ifdef USE_POWER_PINS	
	.VDD(VDD), //Floating VDD pin to trick OpenLane
	.GND(GND),
`endif
	.s(s_top[3:0]),
	.s_bar(s_bar_top[3:0]),
	.x(x_top[3:0]),
	.x_bar(x_bar_top[3:0]),
	.k(k_top[3:0]),
	.k_bar(k_bar_top[3:0]),
	.CLK(clk_top[3:0]),
	.Dis(dis_top[3:0])
);

bitfour_EESPFAL lane2 (
`ifdef USE_POWER_PINS	
	.VDD(VDD), //Floating VDD pin to trick OpenLane
	.GND(GND),
`endif
	.s(s_top[3:0]),
	.s_bar(s_bar_top[3:0]),
	.x(x_top[3:0]),
	.x_bar(x_bar_top[3:0]),
	.k(k_top[3:0]),
	.k_bar(k_bar_top[3:0]),
	.CLK(clk_top[3:0]),
	.Dis(dis_top[3:0])
);

bitfour_EESPFAL lane3 (
`ifdef USE_POWER_PINS	
	.VDD(VDD), //Floating VDD pin to trick OpenLane
	.GND(GND),
`endif
	.s(s_top[3:0]),
	.s_bar(s_bar_top[3:0]),
	.x(x_top[3:0]),
	.x_bar(x_bar_top[3:0]),
	.k(k_top[3:0]),
	.k_bar(k_bar_top[3:0]),
	.CLK(clk_top[3:0]),
	.Dis(dis_top[3:0])
);
Probably need to change
bitfour_EESPFAL_bb.v
also
j
Should I expand output bits to accommodate for the issue?
m
Maybe change the
output
to
inout
on
s
and
s_bar
?
j
Gotcha, that dealt with step 1's error. Now we are at generating PDN section, seems to give the same error as before. What file should I check and provide to advance the troubleshooting process?
m
From the log file, it looks like you might be specifying the module name instead of the instance name.
Copy code
No regex match found for bitfour_EESPFAL0 defined in FP_PDN_MACRO_HOOKS
FP_PDN_MACRO_HOOKS
uses the instance name, ie.
lane0
. Just to avoid problems with escaping json/tcl characters, I suggest creating instance names without
[
]
.
j
I took out the
[]
and `"bitfour_EESPFAL0 VDD GND VDD GND"`out of curiosity from the config.json file. ./flow.tcl got pass the generating PDN step and ran into placement resizer design optimization error. Edit: I made the
DIE_AREA: "0 0 1000 1000"
and that got past
[ERROR DPL-0044] Cell lane0 with height 78865 is taller than any row.
Currently the error is in the Global Routing Resizer Design Optimization step
[ERROR GRT-0076] Net clknet_1_1__leaf_clk_top[2] not properly covered.
m
Progress, I hope. Can you look at the intermediate results to see if the results are reasonable? Maybe try
openroad -gui
j
it looks like the following image. The dimensions for the blackboxed circuit is correct, and having 4 of them is expected since we have done lane0~lane3. I will try to implement the macro_placement.cfg to make sure the blackboxed circuit is not in the corner edit: looks like the macro_placement.cfg I included took the circuits out of the corner since I'm out of the Global Routing Resizer step
In the picture, the detailed routing is reporting 3 violations after optimization. But when I look at the detailed.log, I see it starts with a massive
[WARNING DRT-6000] Macro pin has more than 1 polygon
dump and it started with 305 violations. Is the warning something to be concerned about or this can be mitigated by specifying a smaller die area?
m
Not sure about the macro pin polygons, but I imagine the lef has multple pins defined for the same net. Is that correct? I don’t think it’s a problem.
j
I think that's accurate. Currently the same output pins has been reused for the four instances. I'm going to see if it is a spacing issue using the macro_placement.cfg
I've reduced the number of instanced copy down to 1 and it got pass
step 24 Running Detailed Routing
. Now the error is relating to LVS. It looks like the floating VDD pin is not connected at all.
m
You are correct - the VDD pin does not appear to be connected. Top power rails generally connect to the macro power grid on the top macro metal layer. Currently, I do not see a power grid on your macro. Can you try adding VGND power rails up to metal3 and extend the dummy VDD pin as a power rail?
j
I understand. I will make them pronto and see if the error persists.
I have made the VDD and GND rails however its saying VDD is has no matching pins. Does circuit 1 belong to the top verilog while circuit belong to the gds/lef generated from magic? What is the step to get VDD on magic's(circuit 2?) side as
Net: lane0/VDD
? Another thing is I have to update the macro_placement.cfg to
155 150 N
instead of
150 150 N
to avoid step 24 (Detailed Routing) violation. Why is this a thing? I have included the .log file for that.