I'm looking for a way to concatenate multiple define statements into a singledefine statement, so that I can use it in a case statement.
As an example, have memory addresses that are defined in a header file. I have a case statement that decides if the value should be written to LUTRAM or block ram depending on the address.
I have the following defines:
`define PWM_REPEAT_REG (6'h10) // Number of times to repeat a PWM Pulse
`define PWM_WIDTH_REG (6'h14) // Pulse width in timebase counts
`define PWM_PULSE_PERIOD (6'h1c) // PWM pulse period in timebase counts.
Inside my code i've got a case statement that looks like this:
case(sys_mgr_address)
`PWM_REPEAT_REG, `PWM_WIDTH_REG, `PWM_PULSE_PERIOD : begin // Values for block RAM
ram_a_din <= sys_mgr_write_data;
ram_a_addr <= sys_mgr_address;
ram_a_wr_enable <= 1'b1;
sys_mgr_write_ok <= 1'b1;
update_available <= 1'b1;
end
endcase
The actual design has several addresses and this type of case statement is repeated several times. Rather than type out all the defines over and over for each one, I'd like to create another define that looks like this:
`define PWM_MODULE_BLOCK_RAM_ADDRESSES ({`PWM_REPEAT_REG, `PWM_WIDTH_REG, `PWM_PULSE_PERIOD})
case(sys_mgr_address)
PWM_MODULE_BLOCK_RAM_ADDRESSES : begin // Values for block RAM
ram_a_din <= sys_mgr_write_data;
ram_a_addr <= sys_mgr_address;
ram_a_wr_enable <= 1'b1;
sys_mgr_write_ok <= 1'b1;
update_available <= 1'b1;
end
endcase
^^ The above code does not work since it's concatenating the numbers into a pretty large vector. I've tried some variations, like without the concatenation braces {}, defining it as text, a few different variations of `` (but I'm not sure what exactly that does).
Is there any way to see the expanded macro before compile? Right now it just gives me an error for most of the ones i've tried which doesn't make troubleshooting easy.
Thanks!
You are thinking too hard. All you need to do is put the comma's the macro
`define PWM_MODULE_BLOCK_RAM_ADDRESSES `PWM_REPEAT_REG, `PWM_WIDTH_REG, `PWM_PULSE_PERIOD
Define macro's are just simple expansions of text.
Related
I have 26 variables and each of them contain numbers ranging from 1 to 61. I want for each case of 1, each case of 2 etc. the number 1 in a new variable. If there is no 1, the variable should contain 2.
So 26 variables with data like:
1 15 28 39 46 1 12 etc.
And I want 61 variables with:
1 2 1 2 2 1 etc.
I have been reading about creating vectors, loops, do if's etc but I can't find the right way to code it. What I have done is just creating 61 variables and writing
do if V1=1 or V2=1 or (etc until V26).
recode newV1=1.
end if.
exe.
**repeat this for all 61 variables.
recode newV1 to newV61(missing=2).
So this is a lot of code and quite a detour from what I imagine it could be.
Anyone who can help me out with this one? Your help is much appreciated!
noumenal is correct, you could do it with two loops. Another way though is to access the VECTOR using the original value though, writing that as 1, and setting all other values to zero.
To illustrate, first I make some fake data (with 4 original variables instead of 26) named X1 to X4.
*Fake Data.
SET SEED 10.
INPUT PROGRAM.
LOOP Id = 1 TO 20.
END CASE.
END LOOP.
END FILE.
END INPUT PROGRAM.
VECTOR X(4,F2.0).
LOOP #i = 1 TO 4.
COMPUTE X(#i) = TRUNC(RV.UNIFORM(1,62)).
END LOOP.
EXECUTE.
Now what this code does is create four vector sets to go along with each variable, then uses DO REPEAT to actually refer to the VECTOR stub. Then finishes up with RECODE - if it is missing it should be coded a 2.
VECTOR V1_ V2_ V3_ V4_ (61,F1.0).
DO REPEAT orig = X1 TO X4 /V = V1_ V2_ V3_ V4_.
COMPUTE V(orig) = 1.
END REPEAT.
RECODE V1_1 TO V4_61 (SYSMIS = 2).
It is a little painful, as for the original VECTOR command you need to write out all of the stubs, but then you can copy-paste that into the DO REPEAT subcommand (or make a macro to do it for you).
For a more simple illustration, if we have our original variable, say A, that can take on integer values from 1 to 61, and we want to expand to our 61 dummy variables, we would then make a vector and then access the location in that vector.
VECTOR DummyVec(61,F1.0).
COMPUTE DummyVec(A) = 1.
For a record if A = 10, then here DummyVec10 will equal 1, and all the others DummyVec variables will still by system missing by default. No need to use DO IF for 61 values.
The rest of the code is just extra to do it in one swoop for multiple original variables.
This should do it:
do repeat NewV=NewV1 to NewV61/vl=1 to 61.
compute NewV=any(vl,v1 to v26).
end repeat.
EXPLANATION:
This syntax will go through values 1 to 61, for each one checking whether any of the variables v1 to v26 has that value. If any of them do, the right NewV will receive the value of 1. If none of them do, the right NewV will receive the value of 0.
Just make sure v1 to v26 are consecutively ordered in the file. if not, then change to:
compute NewV=any(vl,v1, v2, v3, v4 ..... v26).
You need a nested loop: two loops - one outer and one inner.
I'm working on a school homework and I'm finding difficulties in outputing an array with values of 1.I used this code,but the simulator keeps filling the signal bar with X
integer index = 0;
initial
begin
for(index=0;index<=7;index = index+1)
begin
data_out[index]<=1;
end
end
endmodule
data_out is declared as output reg [7:0]data_out
Can anyone suggest me anything?
It works now , as i've used wire[7:0] data_out_test and always block. Thank you for your answers
Ok,and next . I have a descending order counter by the posedge clock and another variable suma_de_1 whose value is 12.The counters stars from 31 to 0 and i have the following if condition
`integer index = 0;
always#(posedge clock) begin
for(index=0;index<=31;index = index+1)
begin
if(count > suma_de_1)
data_out[index]<=2'b00;
else data_out[index]<=1;
end end`
check this out to see the result waveform
at that point count becomes smaller than suma_de_1 but it creates another array . I want it to complete the previous array who was full of 0 until then.
Hope I'm clear enough. I want the output in one array,not two
use "locationdata.dta", clear
gen ring=.
* Philly City Hall
gen lat_center = 39.9525468
gen lon_center = -75.1638855
destring(INTPTLAT10), replace
destring(INTPTLON10), replace
vincenty INTPTLAT10 INTPTLON10 lat_center lon_center , hav(distance_km) inkm
quietly su distance_km
local min = r(min)
replace ring=0 if (`min' <= distance_km < 1)
local max = ceil(r(max))
* forval loop does not work
forval i=1/`max'{
local j = `i'+1
replace ring=`i' if (`i' <= distance_km < `j')
}
I am drawing rings by 1 km from a point. The last part of the code (forval) does not work. Something wrong here?
EDIT:
The result for the forval part is as follows:
. forval i=1/`max'{
2. local j = `i'+1
3. replace ring=`i' if `i' <= distance_km < `j'
4. }
(1746 real changes made)
(0 real changes made)
(0 real changes made)
(0 real changes made)
....
So, replacing does not work for i = 2 and beyond.
A double inequality such as
(`min' <= distance_km < 1)
which makes sense according to mathematical conventions is clearly legal in Stata. Otherwise, your code would have triggered a syntax error. However, Stata does not hold evaluation until the entire expression is evaluated. The parentheses here are immaterial, as what is key is how their contents are evaluated. As it turns out, the result is unlikely to be what you want.
In more detail: Stata interprets this expression from left to right as follows. The first equality
`min' <= distance_km
is true or false and thus evaluated as 0 or 1. Evidently you want to select values such that
distance_km >= `min'
and for such values the inequality above is true and returns 1. Stata would then take a result of 1 forward and turn to the second inequality, evaluating
1 < 1
(i.e. result of first inequality < 1), but that is false for such values. Conversely,
(`min' <= distance_km < 1)
will be evaluated as
0 < 1
-- which is true (returns 1) -- if and only if
`min' > distance_km
In short, what you intend would need to be expressed differently, namely by
(`min' <= distance_km) & (distance_km < 1)
I conjecture that this is at the root of your problem.
Note that Stata has an inrange() function but it is not quite what you want here.
But, all that said, from looking at your code the inequalities and your loop both appear quite unnecessary. You want your rings to be 1 km intervals, so that
gen ring = floor(distance_km)
can replace the entire block of code after your call to vincenty, as floor() rounds down with integer result. You appear to know of its twin ceil().
Some other small points, incidental but worth noting:
You can destring several variables at once.
Putting constants in variables with generate is inefficient. Use scalars for this purpose. (However, if vincenty requires variables as input, that would override this point, but it points up that vincenty is too strict.)
summarize, meanonly is better for calculating just the minimum and maximum. The option name is admittedly misleading here. See http://www.stata-journal.com/sjpdf.html?articlenum=st0135 for discussion.
As a matter of general Stata practice, your post should explain where the user-written vincenty comes from, although it seems that is quite irrelevant in this instance.
For completeness, here is a rewrite, although you need to test it against your data.
use "locationdata.dta", clear
* Philly City Hall
scalar lat_center = 39.9525468
scalar lon_center = -75.1638855
destring INTPTLAT10 INTPTLON10, replace
vincenty INTPTLAT10 INTPTLON10 lat_center lon_center , hav(distance_km) inkm
gen ring = floor(distance_km)
I am using the Macro Arrays and Do Over Macro.
I would like to rewrite this code with a do over macro:
if mysequence > 4 then grammar_last_5 = grammar_last_4;
if mysequence > 3 then grammar_last_4 = grammar_last_3;
if mysequence > 2 then grammar_last_3 = grammar_last_2;
if mysequence > 1 then grammar_last_2 = grammar_last_1;
So my Do Over would look something like:
%do_over(values=2-5, phrase= if mysequence > %eval(6-?) then grammar_last_%eval(7-?) = grammar_last_%eval(6-?);)
But that doesn't work.
Does anyone know how this can be done?
Thanks!!
Adam
For others wondering, the macros appear to be available here: http://www.sascommunity.org/wiki/Tight_Looping_with_Macro_Arrays
You've got a problem though. You're trying to pass in %eval(6-?) and other functions like text to the %do_over macro. Its going to try to compute that function and pass the result to the macro, and because its finding a character in what should be a mathematical operation, I'm guessing it subsequently is throwing a bit of a tantrum.
What's more, a way to do what you want doesn't seem like it would be forthcoming, because you'd need to mask the function from the macro compiler as you're feeding it in as an argument, but then unmask it to the macro compiler as its actually being used by do_over, and I'm guessing do_over isn't going to understand what you want without rewriting its logic even if you succeeded.
May I humbly suggest your own macro code as a starting solution. Something like:
%do i = 5 %to 2 %by -1;
if mysequence > %eval(&i - 1) then grammar_last_&i = grammar_last_%eval(&i - 1);
%end;
This should produce the text you want, though you would need to put it in your own macro, and call it in a data step, as it wouldn't make much sense anywhere else.
If you're going to want something more generalized, you're going to have to get your hands much much messier...
I took a quick look at the macro and it looks like they use macro quoting functions which could be interfering with the execution of your %eval functions.
If this is the case then you would have to custom edit %do_over() so that it didn't do this. If so then it's probably not worth the effort. It would be easier to write your own one-off macro to achieve your goal.
You don't need a macro for that, unless you've got something you're not telling us.
if mysequence > 4 then grammar_last_5 = grammar_last_4;
if mysequence > 3 then grammar_last_4 = grammar_last_3;
if mysequence > 2 then grammar_last_3 = grammar_last_2;
if mysequence > 1 then grammar_last_2 = grammar_last_1;
->
array grammars grammar_last:;
do _t = 4 to 1 by -1; *or, _t = dim(grammars)-1 to 1 by -1;
if mysequence > _t then grammars[_t+1]=grammars[_t];
end;
I have made some c code for a program, which does some psycho-acoustics on sound data.
There is a piece of code which runs very slowly.
I think it would be best to use a look up table. How would one go about implementing it?
Any pointers or help would be appreciated! :)
Your values are not equidistant so it is not that easy. But its still possible: take your greatest common divisor of all your condition-values (thats here 50) and then make your table
byteout = lut[difference/50 + 12];
And in the lookup table you can just use your values in the posted order, where you duplicate the entries in case your stepping is 100.
Btw it just see, there is a mistake, all your negative cases are catched by your first <=0 (my example assumes that you want to omit the first case).
Firstly, take a look at where you want that first check against 0, as it makes all of your negative checks pointless.
Secondly, I would probably construct a lookup table as an array of 1300 elements, offset by 500 (your lowest negative value). Each element would be the result you want when you look up that number. If you are looking for something less than -500, don't check the array.
So it would look something like this:
table[0] = 0b0110; // -500 through -599
table[1] = 0b0110;
...
table[100] = 0b0101; // -400 through -499
table[101] = 0b0101;
...
Lookup would be:
if (value <= -600) {
return 0b0111;
}
else {
return table[value + 600];
}
It's a small enough number of values that the size of the array is not prohibitive. Initialize with a loop at the beginning of your program.
Binary search for the win.
Store all possible values in an array, and be sure to sort them.
Start in the middle and see if difference is less than that value. If so, move to the middle of what's left of your cursor and try again. If not, move to the right. Keep going until you find the value you want, and then use that.
Your array could be of structs that have the minimum value and the corresponding byteout value.
EDIT: To clear up possible misunderstandings, with "every possible value" I don't mean every number between -1400 and 1400, just values you check against in your original code.
Let's look at the first bit:
if (difference <= 0)
byteout = 0b0000;
else if (difference <= -600)
byteout = 0b0111;
Let's say you have a value of -601.
Is it <= 0? Yes, so byteout = 0b0000;
you never get to the -600. So effectively, ALL negative values are 0b0000. This may or may not be by design, but if it is you can get rid of all other negative values.
Otherwise, I would consider reducing this to a formula (with as few branches as possible) or going with #Ebomike's solution of a precomputed lookup table and binary search.