Invoking write/read_reg vr_ad macro from a virtual sequence in Specman - specman

Is there a way that a virtual sequence can directly call a vr_ad write_reg or read_reg macro without me having to create a vr_ad_sequence that does the same thing?
To illustrate more clearly, here is my current implementation:
<'
extend vr_ad_sequence_kind : [WR_DMA_POLL];
extend WR_DMA_POLL vr_ad_sequence {
!dma_poll : DMA_POLL vr_ad_reg;
body() #driver.clock is only {
write_reg dma_poll val 0xdeadbeef;
};
};
extend MAIN soc_tb_virtual_sequence {
!write_dma_poll : WR_DMA_POLL vr_ad_sequence;
body() #driver.clock is only {
message(LOW, "TEST START");
do write_dma_poll on driver.reg_driver;
};
};
'>
Why can't it be, or is it possible to implement this way?
extend MAIN soc_tb_virtual_sequence {
!dma_poll : DMA_POLL vr_ad_reg;
body() #driver.clock is only {
message(LOW, "TEST START");
write_reg {.dest_driver == driver.reg_driver} dma_poll;
read_reg {.dest_driver == driver.reg_driver} dma_poll;
};
};
Thank you in advance for any explanation.

This is possible starting with vr_ad 13.20 (or maybe slightly older). You almost had it in your question. The correct syntax is:
extend MAIN soc_tb_virtual_sequence {
!dma_poll : DMA_POLL vr_ad_reg;
body() #driver.clock is only {
message(LOW, "TEST START");
write_reg {.driver == driver.reg_driver} dma_poll;
read_reg {.driver == driver.reg_driver} dma_poll;
};
};
The first set of {...} delimits the operation generate block, where you can constrain how to access the register. These constraints will be passed to the vr_ad_operation that gets generated as part of the access.

Related

Borrowing Array method to an object with call

I just come across the concept of decorator and apply-call methods.
Why should I use an apply method here, even if it works without that. I can just pass "return func(...args)" and it still works. I understood the concept if I was working with an object method while having a returning this I should have used "apply" or "call",but why is it forwarding the call here with a function? On top of that, how the ".calls" property is getting passed to work.calls ?
function work(a, b) {
alert( a + b );
}
function spy(func) {
function wrapper(...args) {
wrapper.calls.push(args);
return func.apply(this, args);
}
wrapper.calls = [];
return wrapper;
}
work = spy(work);
work(1, 2);
work(4, 5);
for (let args of work.calls) {
alert( 'call:' + args.join() );
}

Is there "parallel all of" in Specman?

Let’s assume I have this unit
unit agent {
init_all_regs() #clock is {…};
};
I have a list of agents, the number of agents vary. I want to call the method init_all_regs() all of the agents, so that all of them run in parallel.
Is there some combination of “all of” and “for each” syntax?
There is no "all of for each" syntax, but there is easy to implement with existing syntax. For example, you can use objections. Define an objection_kind, and use it to synchronize.
for example:
extend objection_kind :[AGNETS_CHECK_REGS];
unit agent {
init_all_regs()#clk is {
raise_objection(AGNETS_CHECK_REGS);
//...
drop_objection(AGNETS_CHECK_REGS);
};
};
extend env {
my_method() #clock is {
for each in agents {
start it.init_all_regs();
};
wait cycle;
while get_objection_total(AGNETS_CHECK_REGS) > 0 {
wait cycle;
};
};
};
Another option is to use a counter, implemented with static member. One disadvantage is that it needs more lines.
Something like this -
unit agent {
static active_counter : int = 0;
static increase_active_counter() is {
active_counter += 1;
};
////....
init_all_regs()#clk is {
increase_active_counter();
//....
decrease_active_counter();
};
};
extend env {
scenario() #any is {
agent::init_active_counter();
for each in agents {
start it.init_all_regs();
};
wait cycle;
while agent::get_active_counter() > 0 {
wait cycle;
};
};
};

SweetJS : Write a macro for a specific library

I'm currently working on a little project which consists about writing macros for Ramda. Here is an example :
let map = macro {
rule { $f $array } => { R.map($f, $array) }
rule { $f } => { R.map($f) }
}
I tried to compile this simple sample of code as a beginning :
var R = require('ramda');
function log (value) {
console.log(value);
}
map log [1, 2, 3];
Because of hygiene, the compiled code looks like this :
var R$759 = require('ramda');
function log$761(value$762) {
console.log(value$762);
}
R.map(log$761)[1, 2, 3];
My problem is that I don't know how to make reference to ramda.
Has anyone tried to write macros for a specific library and encountered this problem ?
At the moment the ways to do it are a little hacky. In the next release when we get ES6 modules this will actually be taken care of automatically for you but until then the best option is to have an initialization macro (this is what ki and contracts.js do). This works by having a shared variable in scope for all of your macros and then having the user first invoke an import macro that does the necessary require:
var r_lib;
macro import {
rule { $name from $path } => {
r_lib = require($path);
}
}
let map = macro {
rule { $f $l } => { r_lib.map($f, $l) }
}
import R from "ramda"
map log [1,2,3]

Specman UVM: How update a value of a register when the value was written to another register?

(in my verification environment we use vr_ad package.). I try to implement the next:
When data is written to one of the registers (timer_load), another register (timer_bgload) should be updated with the same data.
I've found the next example in UVM User Guide:
// Attaching the target register file to the broadcasted register
extend ex_c_bus_env {
post_generate() is also {
xcore_regs.vr_ad_rx_data.attach(xbus_regs);
};
};
// Implement the broadcast:
// When writing to register VR_AD_RX_DATA in XCORE vr_ad_reg_file,
// propagate the value to the VR_AD_XBUS_DATA register in ACTIVE_XBUS.
extend ACTIVE_XBUS vr_ad_reg_file {
indirect_access( direction : vr_ad_rw_t, ad_item : vr_ad_base) is {
if ad_item is a VR_AD_RX_DATA vr_ad_reg (d) {
vr_ad_xbus_data.write_reg_val(d.get_cur_value());
};
};
};
My registers:
reg_def TIMER_LOAD_0 TIMER 20'h00010 {
reg_fld timer_load : uint (bits : 32) : RW : 0xffff;
};
reg_def TIMER_BGLOAD_0 TIMER 20'h00014 {
reg_fld timer_bgload : uint (bits : 32) : RW : 0xffff;
};
reg_def TIMER_BGLOAD_1 TIMER 20'h00028 {
reg_fld timer_bgload : uint (bits : 32) : RW : 0xffff;
//another reg with the same instance name
};
My code for updating the timer_bgload register after a data was written to tiemr_load:
extend TIMER vr_ad_reg_file {
indirect_access( direction : vr_ad_rw_t, ad_item : vr_ad_base) is {
if ad_item is a TIMER_LOAD_0 vr_ad_reg (d) {
timer_bgload.write_reg_val(d.get_cur_value());
};
};
};
unit timer_env_u like any_env {
post_generate() is also {
timer_regs.timer_load_0.attach(timer_regs.timer_bgload_0.timer_bgload);
};
};
I get a compilation error:
*** Error: No such variable 'timer_bgload'
at line 17 in #timer_reg_db
timer_bgload.write_reg_val(d.get_cur_value());
I really appreciate any help.
You can attach the timer_load register to the timer_bgload register directly and implement indirect_access(...) there:
// attach the regs
extend TIMER vr_ad_reg_file {
post_generate() is also {
timer_load_0.attach(timer_bgload_0);
};
};
// implement indirect_access()
extend TIMER_BGLOAD_0 vr_ad_reg {
indirect_access(direction : vr_ad_rw_t, ad_item : vr_ad_base) is {
if direction == WRITE and ad_item is a TIMER_LOAD_0 vr_ad_reg (d) {
write_reg_val(d.get_cur_value());
};
};
};
I don't know why the Cadence example took the long route of attaching the register file to the indirect register.
Also, if you have more than one TIMER_LOAD/BGLOAD registers (seems like you may have 2), then the best thing to do is define the types first:
// define register types without instantiation in reg_file
reg_def TIMER_LOAD {
reg_fld timer_load : uint (bits : 32) : RW : 0xffff;
};
reg_def TIMER_BGLOAD {
reg_fld timer_bgload : uint (bits : 32) : RW : 0xffff;
};
After you define the types, you instantiate them in the register file manually as many times as you need to. Have a look in the manual, there is an example showing you exactly how to do it.
This means that it's enough to implement the indirect_access(...) method in the TIMER_BGLOAD subtype (only once) as opposed to two times (for TIMER_BGLOAD_0 and TIMER_BGLOAD_1).
I'd implement it with post_access, something like that:
extend TIMER_LOAD_0 TIMER vr_ad_reg {
post_access(operation : vr_ad_rw_t) is {
if operation == WRITE {
var rgf := get_access_path()[0].as_a(TIMER vr_ad_reg_file);
rgf.timer_bgload_0.timer_bgload = timer_load;
};
};
};
Pay attention, that it might not work on first hit. If it's not, I'd build it gradually, starting with 'empty' code like this:
extend TIMER_LOAD_0 TIMER vr_ad_reg {
post_access(operation : vr_ad_rw_t) is {
print me, operation;
};
};
And putting a breakpoint in the print statement, opening a data browser, looking what are the exact names of the fields we got there, try to access them from Specman CLI - and when it works - code it back.

how can i know if i am using specman 64/32 bit during runtime

I want to write some e code that is conditioned by the used specman architecture (64/32 bit).
What i need will look like:
if (specman 64 bit) {
do something
} else {
do something else
};
One can do so, by using the predefinef SN_64_BIT define.
I.e , one can condition the appearance of code by this define, for example:
<'
extend sys {
run() is also{
#ifdef SN_64_BIT then
{ out("64 bit"); }
#else
{ out("32 bit "); }
};
};
'>