Skip to content

Instantly share code, notes, and snippets.

@dvtalk
Last active June 6, 2022 02:59
Show Gist options
  • Save dvtalk/692f45bba567aaeae98f61f63d867058 to your computer and use it in GitHub Desktop.
Save dvtalk/692f45bba567aaeae98f61f63d867058 to your computer and use it in GitHub Desktop.
uvm_semaphore, wrap around std::semaphore class of SystemVerilog
// https://dvtalk.me/2021/10/03/uvm-pool-and-semaphore/
class uvm_semaphore extends uvm_object;
protected semaphore m_semaphore;
protected string m_name;
protected int m_keyCount;
protected int m_remainKeyinBucket;
protected bit m_expandBucket_en;
function new (string name="", int keyCount=0);
super.new(name);
m_semaphore = new(keyCount);
m_name = name;
m_keyCount = keyCount;
m_remainKeyinBucket = keyCount;
m_expandBucket_en = 1;
uvm_report_info("SEMAPHORE", $psprintf("[%s] Create new semaphore, number of keys: %0d",name, keyCount));
endfunction
virtual function void set_keyCount(int keyCount=0);
if (keyCount > m_keyCount) begin
// if new keyCount is greater than current m_keyCount, just put more keys in the bucket
this.put(keyCount-m_keyCount);
end
else if (keyCount < m_keyCount) begin
// if new keyCount is smaller than current m_keyCount,
// create new semaphore if all keys are in the bucket.
if (m_remainKeyinBucket == m_keyCount) begin
m_semaphore = new(keyCount);
m_keyCount = keyCount;
m_remainKeyinBucket = keyCount;
uvm_report_info("SEMAPHORE", $psprintf("[%s] Create new semaphore, number of keys: %0d",m_name, keyCount));
end
else begin
uvm_report_error("SEMAPHORE",$psprintf("[%s] Semphore key is already used, cannot set the keyCount to smaller than %0d",m_name, m_keyCount));
end
end
endfunction
virtual function void put(int keyCount=1);
m_semaphore.put(keyCount);
if ((m_remainKeyinBucket + keyCount)> m_keyCount) begin
if (is_expand_bucket_en()) begin
uvm_report_warning("SEMAPHORE", $psprintf("[%s] [PUT] ADDING %0d MORE keys to the orginal total keys (%0d)",m_name, (m_remainKeyinBucket+keyCount)-m_keyCount, m_keyCount ));
m_remainKeyinBucket += keyCount;
m_keyCount = m_remainKeyinBucket;
uvm_report_info("SEMAPHORE", $psprintf("[%s] [PUT] Remaining keys in bucket: %0d, total keys of semaphore: %0d", m_name, m_remainKeyinBucket, m_keyCount));
end
else begin
uvm_report_warning("SEMAPHORE", $psprintf("[%s] [PUT] Used keys : %0d, total keys of semaphore: %0d", m_name, m_keyCount - m_remainKeyinBucket, m_keyCount));
uvm_report_warning("SEMAPHORE", $psprintf("[%s] [PUT] Trying to put %0d keys to the bucket. Only put %0d keys in the bucket, to allow expanding the bucket keys, call <semaphore handle>.set_expand_bucket_en(1'b1); " ,m_name, keyCount, m_keyCount-m_remainKeyinBucket));
m_remainKeyinBucket = m_keyCount;
uvm_report_info("SEMAPHORE", $psprintf("[%s] [PUT] Remaining keys in bucket: %0d, total keys of semaphore: %0d", m_name, m_remainKeyinBucket, m_keyCount));
end
end
else begin
uvm_report_info("SEMAPHORE", $psprintf("[%s] [PUT] Put %0d keys in bucket, remaining keys in bucket: %0d, total keys of semaphore: %0d", m_name, keyCount, m_remainKeyinBucket, m_keyCount));
end
endfunction
virtual task get(int keyCount=1);
m_semaphore.get(keyCount);
m_remainKeyinBucket -= keyCount;
uvm_report_info("SEMAPHORE", $psprintf("[%s] [GET] Get %0d keys from bucket, remaining keys in bucket: %0d, total keys of semaphore: %0d", m_name, keyCount, m_remainKeyinBucket, m_keyCount));
endtask
virtual function int try_get(int keyCount=1);
int try_get = m_semaphore.try_get(keyCount);
if (try_get==0) begin
uvm_report_info("SEMAPHORE", $psprintf("[%s] [TRY_GET] Try Get %0d keys from bucket UNSUCCESSFUL, remaining keys in bucket: %0d, total keys of semaphore: %0d",m_name,keyCount, m_remainKeyinBucket, m_keyCount));
end
else begin
m_remainKeyinBucket -= keyCount;
uvm_report_info("SEMAPHORE", $psprintf("[%s] [TRY_GET] Try Get %0d keys from bucket, remaining keys in bucket: %0d, total keys of semaphore: %0d", m_name, keyCount, m_remainKeyinBucket, m_keyCount));
end
endfunction
virtual function int get_remaining_keys();
return this.m_remainKeyinBucket;
endfunction
virtual function int get_total_keys();
return this.m_keyCount;
endfunction
virtual function void set_expand_bucket_en(bit expand_bucket_en);
this.m_expandBucket_en = expand_bucket_en;
endfunction
virtual function bit is_expand_bucket_en();
return this.m_expandBucket_en;
endfunction
endclass: uvm_semaphore
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment