Here's what I want to do:
There are several problems with stretching an instance (moving it while keeping it attached to wires, etc):
1. Poor UX - the user has to use more effort for something very simple. In Cadence, one merely clicks and drags to "stretch". In Cadence, CTRL + click and drag (RMB) is for moving WITHOUT retaining connections.
2. As one observes, after the action is completed, some objects are in a selected state. Therefore, the user cannot simply click and drag (using CTRL if necessary) on another object. The user must first press ESC to clear the selection, or click on a blank region
The desired enhancements:
(Introduce variables as needed so that default behavior from the starting point repo of SS is unchanged)
1. User will be able to set a variable so that the effect of CTRL being pressed is the reverse of the current situation - that is, after the update is checked in, if the user presses CTRL and clicks-and-drags on a wire or instance, it will be moved without retaining connections. More importantly, the user will not have to press CTRL to click-and-drag on an instance or wire to "stretch it (aka move it with wires remaining connected (redrawn as necessary))
2. As seen in the video, wires are stretched in "any angle" mode which is highly inconvenient. However, orthogonal routing capability has been introduced in a recent commit. Therefore, when wires need to be stretched, they will be redrawn introducing only right angles if necessary.
3. After a stretch, the selected set will remain unchanged. That is, whatever objects were part of the selected set will remain selected after the stretch.
And here's one plan:
Walk through the code starting with that the 'y' key does. It sets a variable. Where is that variable used?
Luckily, the oracle steps in:
is there a C debugger that can tell me which lines of code were hit after I run the program? Maybe it's called a profiler?
Yes, you're on the right track! What you're looking for is code coverage analysis — a feature commonly found in debuggers, profilers, or dedicated coverage tools. These tools track which lines of your C code were executed during a run.
1. gcov (with gcc)
A classic coverage tool that works with GCC.
In your makefile:
ifeq ($(COVERAGE),1)
CFLAGS += -fprofile-arcs -ftest-coverage -O0 -g
LDFLAGS += -fprofile-arcs -ftest-coverage
endif
If you have productivity-OCD like I do, looking at the .gcov gets old very fast. Thankfully, there's lcov:
sudo apt install lcov
lcov --capture --directory . -output-file coverage.info --rc lcov_branch_coverage=1
genhtml coverage.info -output-directory out --ignore-errors unmapped --branch-coverage --rc genhtml_branch_coverage=1
Here's an output: (All I did after launching was open-recent, and then move one instance, and then close xschem).
4373 [ + - - + : 1 : if(draw_xhair && (use_cursor_for_sel || crosshair_size == 0)) { - - ] 4374 : 1 : sel = find_closest_obj(xctx->mousex_snap, xctx->mousey_snap, 0); 4375 : : } else { 4376 : 0 : sel = find_closest_obj(xctx->mousex, xctx->mousey, 0); 4377 : : } 4378 : 1 : dbg(1, "sel.type=%d\n", sel.type); 4379 : : /* determine if closest object was already selected when button1 was pressed */ 4380 [ - - - - : 1 : switch(sel.type) { - - + - ] 4381 [ # # ]: 0 : case WIRE: if(xctx->wire[sel.n].sel) already_selected = 1; break; 4382 [ # # ]: 0 : case xTEXT: if(xctx->text[sel.n].sel) already_selected = 1; break; 4383 [ # # ]: 0 : case LINE: if(xctx->line[sel.col][sel.n].sel) already_selected = 1; break; 4384 [ # # ]: 0 : case POLYGON: if(xctx->poly[sel.col][sel.n].sel) already_selected = 1; break; 4385 [ # # ]: 0 : case xRECT: if(xctx->rect[sel.col][sel.n].sel) already_selected = 1; break; 4386 [ # # ]: 0 : case ARC: if(xctx->arc[sel.col][sel.n].sel) already_selected = 1; break; 4387 [ - + ]: 1 : case ELEMENT: if(xctx->inst[sel.n].sel) already_selected = 1; break; 4388 : 0 : default: break; 4389 : : } /*end switch */ 4390 : :
This is interesting isn't it - it tells us that the instance is represented by "ELEMENT" in the code - yup - Stefan loves to confuse his audience. And there's some info about what the various tests in the conditionals returned.
Now, look at the below output and tell me what tip I want to pass on about C code structure that might help when using gcov?
4374 [ - - - - : 1 : switch(sel.type) { - - + - ] 4375 [ # # ]: 0 : case WIRE: if(xctx->wire[sel.n].sel) already_selected = 1; break; 4376 [ # # ]: 0 : case xTEXT: if(xctx->text[sel.n].sel) already_selected = 1; break; 4377 [ # # ]: 0 : case LINE: if(xctx->line[sel.col][sel.n].sel) already_selected = 1; break; 4378 [ # # ]: 0 : case POLYGON: if(xctx->poly[sel.col][sel.n].sel) already_selected = 1; break; 4379 [ # # ]: 0 : case xRECT: if(xctx->rect[sel.col][sel.n].sel) already_selected = 1; break; 4380 [ # # ]: 0 : case ARC: if(xctx->arc[sel.col][sel.n].sel) already_selected = 1; break; 4381 [ - + ]: 1 : case ELEMENT: if(xctx->inst[sel.n].sel) already_selected = 1; break; 4382 : 0 : default: break; 4383 : : } /*end switch */ 4384 : : 4385 : : /* Clicking and drag on an instance pin -> drag a new wire */ 4386 [ + - + - ]: 1 : if(xctx->intuitive_interface && !already_selected) { 4387 [ - + ]: 1 : if(add_wire_from_inst(&sel, xctx->mousex_snap, xctx->mousey_snap)) 4388 : 0 : return; 4389 : : } 4390 : : 4391 : : /* Clicking and drag on a wire end -> drag a new wire */ 4392 [ + - + - ]: 1 : if(xctx->intuitive_interface && !already_selected) { 4393 [ - + ]: 1 : if(add_wire_from_wire(&sel, xctx->mousex_snap, xctx->mousey_snap)) 4394 : 0 : return; 4395 : : }
You're smart! You got it!
You can code a short if statement as
if( conditon) whatever;
or
if( condition)
whatever;
But, think which one gets you more value out of gcov. That's right! If you can see that the whatever wasn't run, that tells you how the if turned out :)
If you want to re-run the same program and look at gcov output, which files do you need to delete before running? Do you need to run make again?
🧹 You do need to delete old .gcda and .gcov files:
| File Type | Purpose | Delete Before Re-run? |
|---|---|---|
.gcno | Generated at compile time — stores control-flow graph info | ❌ No (only delete if recompiling) |
.gcda | Generated at runtime — stores execution counts | ✅ Yes |
.gcov | Generated by gcov tool from .gcda + .gcno | ✅ Yes |
No comments:
Post a Comment