Tuesday, July 23, 2019

Perl Notes

system()

Using the Perl system() function
The system() function returns two numeric values folded into one. The first is the Unix signal (e.g INT=2, QUIT=3, KILL=9), if any, that terminated the command. This is stored in the lower eight bits returned. The next higher eight bits contain the exit code for the command you executed.

The result is a compound numeric value, not a logical value. This also reads inverted and is confusing. If you need more information on error, then you can break up the return code:
my $status = system("rotate_quickly.pl"); 
my $signal = $status & 0xff; 
my $exit_code = ($status >> 8) & 0xff;


String

how to keep all special characters in a string?
the use of q() and quotemeta: stackoverflow post on excaping in perl

Monday, July 15, 2019

UVM Notes

This article is to list down the most used constructions of UVM to my personal understanding.

UVM simulator steps

  • VCS(Synopsys)
  • IUS(Cadence)
  • Questa(Mentor)
1. set $UVMHOME to instal dir of required UVM library
2. Use irun option -uvmhome to reference $UVMHOME
3. Use incdir to reference any included file directories
%irun -f run.f

run.f:
-uvmhome $UVMHOME
-incdir .../sv
.../sv/tb_pkg.sv
top.sv

top.sv:
module top();
    import uvm_pkg::*;
    import tb_pkg::*;
    initial begin
        //run test
        ...
    end
endmodule: top

Debugging case: 
when using 3 step compile on vcs, vlogan and elab must both add uvm_dpi.cc to actually compile the c. add the file in file list does not work. 
if using 1 step compile, then just need to include the file in filelist. 


UVM Directory Structure

contains two kinds of code:

UVM_ROOT UVM_TOP

Tips: (1) debug features
uvm_top.print_topology();  //advised to be called from end_of_elaboration_phase

=======================================
If you look into the uvm source code, run_test() task is actually a task defined in the class uvm_root. it's the implicit top-level and phase controller for all UVM components. the UVM automatically creates a single instance of <uvm_root> that users can access via the global (uvm_pkg-scope) variable uvm_top. 
  • long time confusion solved: the run_test() called in top tb module is defined in uvm_globals.svh which actually calls the run_test() in uvm_root.
  • uvm_test_top is not a variable in uvm_root, how can you access that with uvm_root?
  • class uvm_root extends uvm_component
  • const uvm_root uvm_top = uvm_root::get();
  • uvm_top is the top-level component, and any component whose parent is specified as NULL becomes a child of uvm_top.
  • uvm top manages the phasing for all components.
  • set globally the report verbosity, log files, and actions(?).
  • Because uvm_top is globally accessible (in uvm_pkg scope(?)), UVM's reporting mechanism is accessible from anywhere outside uvm_component, such as in modules and sequences.

UVM Configuration

1) uvm_config_db

  • uvm_config_db#(int)::set(this, "env.agent", "is_active", UVM_PASSIVE);
  • uvm_config_db#(int)::set(null, "uvm_test_top.env.agent", "is_active", UVM_PASSIVE);
  • uvm_config_db#(int)::set(uvm_root::get(), "uvm_test_top.env.agent", "is_active", UVM_PASSIVE);//equivalent to using null
  • uvm_config_db#(int)::set(null, "*.env.agent", "is_active", UVM_PASSIVE);
  • uvm_config_db#(int)::set(null, "uvm_test_top.env*", "is_active", UVM_PASSIVE);
  • Database must be type parameterized. this allows config db to be created for any standard or user-defined type; and allows better compile time checking.
  • Methods are static
  • Methods use a specific contxt argument, whi is usually this; unless the set is called from the top module, in which case it must be assigned to null
  • syntax: static function void set(uvm_component cntxt, string inst_name, string field_name, ref T value)
  • syntax: static function void get(uvm_component cntxt, string inst_name, string field_name, ref T value)
    • get is only required when set is called from the top level module or outside the build phase
  • syntax: static function bit exists(uvm_component cntxt, string inst_name, string field_name, bit spell_chk = 0)
  • syntax: static task wait_modified(uvm_component cntxt, string inst_name, string field_name)
  • inst_name may contain wildcards or regular expression syntax
  • for object, interfaces or user-defined types, use uvc_config_db
  • for run-time configuration, use uvc_config_db


2) a specialized cfg task is set_config_* for uvm_component class, where * can be int, string or object, depending on type of config property:

  • config settings are automatically resolved in UVM build phase; that is because apply_config_settings() is executed in the build phase (when super.build_phase() is called in any uvm_component class). settings are applied only when match is found, if not found, field names will be unset, and mismatched configuration set's should be listed at end of simulation.
  • syntax: virtual function void set_config_in (string inst_name, string field, bitstream_t value)
    • inst_name is relative pathname to a specific component instance from the component where the method is called
    • field is a string containing a config property name of the instance class
    • set build options before calling super.build_phase; this is also why the parameters are strings, because the components and fields does not exist yet.
    • set_config_int("env.agent", "is_active", UVM_PASSIVE);
    • set_config_int("*", "recording_detail", 1);//default is 0, by enabling the recording details for every component, transactions can be viewed in the waveform window(?)
  • the creation of the agent instance in the parent build_phase() triggers the execution of the build_phase() of the agent instance.
  • config property must be automated in the component where declared (field registered)
  • Config settings in higher scope take precedence over lower scopes.
  • Config settings in the same scope conform to "last one in wins"

UVM Field Automation

#Non-array
1) `uvm_field_int (<field_name>, <flags>)
2) `uvm_field_object (<field_name>, <flags>)
3) `uvm_field_string (<field_name>, <flags>)
4) `uvm_field_event (<field_name>, <flags>)

#static Array:
1) `uvm_field_sarray_enum (<enum_type>, <field_name>, <flags>)
2) `uvm_field_sarray_int (<field_name>, <flags>)
3) `uvm_field_sarray_object (<field_name>, <flags>)
4) `uvm_field_sarray_string (<field_name>, <flags>)
#dynamic Array:
1) `uvm_field_array_enum (<enum_type>, <field_name>, <flags>)
2) `uvm_field_array_int (<field_name>, <flags>)
3) `uvm_field_array_object (<field_name>, <flags>)
4) `uvm_field_array_string (<field_name>, <flags>)
#dynamic Array:
1) `uvm_field_queue_enum (<enum_type>, <field_name>, <flags>)
2) `uvm_field_queue_int (<field_name>, <flags>)
3) `uvm_field_queue_object (<field_name>, <flags>)
4) `uvm_field_queue_string (<field_name>, <flags>)

#associative Array:
1) `uvm_field_aa_<d_type>_<ix_type>

#flags
UVM_NOVOMPARE

#the do_* functions are worth more discussion later. 

uvm_factory

b extends a, c extends a, override(a,c)
will b be affected?
Tips: (1) how to use factory debug features. 
uvm_factory::get().print(); //prints the uvm_factory details like registration and override. can be called from build phase, connect phase or mostly likely end_of_elaboration_phase. 

UVM Phasing

Tips:(1) phasing debug features (not very useful)
sim option +UVM_PHASE_TRACE
(2) objection debugging 
sim option +UVM_OBJECTION_TRACE

UVM_sequence

start_item()
finish_item()
get_response()
driver: 
seq_item_port.get_next_item(), 
seq_item_port.item_done(), 
seq_item_port. put(resp)

UVM_POOL

uvm_object_string_pool #(T)
pool.get(string) #get object by a name

Scoreboard

A scoreboard normally consists of 3 components of functions:
1) reference model/transfer function
     c++, systemC or systemverilog: a) existing C model; b) create model, not in collaboration with design team( duplication of errors)
2) Data Storage
     model output instant, DUT takes time to output. Need to store data (and synchronization)
    Queue: output data in same order as input order
    Associative Array: out of order output. Key unique and knonw for input and output. herefore, key is either: a) untransformed port of data, or b) can be generated from data
3) comparison/check logic

Scoreboard internals:
    update counter, tracking received, dropped, matched, and mismatched
    report_phase, print summary of statistics
    end of simulation: check scoreboard queues are empty

Scoreboard must create a new copy of received data item by cloning, before writing the cloned packet to the queue.

UVM TLM Communication bwtween Components

TLM concepts: Port and Imp
    Data Flow: producer create data, consumer consume data
            Producer ---data---> Cosumer
    Control Flow: Initiator sends request to Target
            Initiator ---request---> Target
    producer is initiator: write operation, also called push/put: e.g. analysis connections
    producer is target: read operation, also called pull/get

Port: TLM connection object for Initiator
Imp (implementation): TLM connection object for target.
Export:
symbols: square(port), circle(imp), triangle(export)
port.connect(Imp)
port.connect(Export)

TLM Analysis Interface
uvm_analysis_port #(data type) ap_out
ap_out = new("ap_out", this);

`uvm_analysis_imp_decl(_foo)
uvm_analysis_imp_foo #(data type) foo_in
`uvm_analysis_imp_decl(_bar)
uvm_analysis_imp_foo #(data type) bar_in

function void write_foo(input ---);
endfunction
function void write_bar(input---);
endfunction

...ap_out.connect(...ap_in)


Complex Module UVC connection(external to intermal)
two ways:
1. Module monitor: all external connections are made to this monitor and monitor is responsible for routing connections to other component in the UVC.
the good:  Single, central location for connecting external TLM interfaces.
the bad: at the expense of additional internal interface connections to other components.

2. Module connections: external TLM interfaces are placed on UVC itself, then routed using hierarchical connections and not separate TLM interface. use of TLM export object
the good: fewer TLM connections
the bad: losing some readability

Port initiators can be connected to port, export, or imp targets.
Export initiators can be connected to export or imp targets.
Imp cannot be a connection initiator. Imp is a target only, and is always the last connections object on a route.

TLM FIFO

Analysis FIFO
uvm_tlm_analysis_fifo is a specialization of uvm_tlm_fifo:
unbounded (size=0)
analysis_export replaces put export, support analysis write method.

uvm_analysis_port ---> analysis_export---analysis_fifo---get_peek_export <---scoreboard_get_port

uvm_tlm_analysis_fifo #(data type) tb_fifo = new("...", this);
uvm_get_port $(data type) sb_in = new("...", this);
function void connect_phase();
    sb_in.connect(tb_fifo.get_peek_export)
endfunction

by the way, analysis fifo's blocking_get_export is just an alias to get_peek_export










Thursday, July 11, 2019

Wednesday, July 10, 2019

Ethernet Protocol Notes

Gigabit Ethernet:
this post is about 1G Physical Coding Sublayer (PCS), and explains scrambler/descrambler. Note the way it explains Bit Error Rate (BER).
Gigabit Ethernet 1000BASE-T

scrambling -> Spread Spectrum

C Programming

Header Files and Includes https://cplusplus.com/forum/articles/10627/ https://stackoverflow.com/questions/2762568/c-c-include-header-file-or...