scc 2025.09
SystemC components library
ordered_semaphore.cpp
1/*******************************************************************************
2 * Copyright 2019 MINRES Technologies GmbH
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *******************************************************************************/
16
17#include "ordered_semaphore.h"
18#include "report.h"
19#include "sysc/communication/sc_communication_ids.h"
20#include "sysc/kernel/sc_wait.h"
21#include <util/strprintf.h>
22
23namespace scc {
24
25using namespace sc_core;
26
27// ----------------------------------------------------------------------------
28// CLASS : sc_semaphore
29//
30// The sc_semaphore primitive channel class.
31// ----------------------------------------------------------------------------
32
33// error reporting
34namespace {
35auto gen_unique_event_name(const char* modifier) -> std::string {
36 auto str = std::string("$$$$kernel_event$$$$_") + "_" + modifier;
37 return std::string(sc_core::sc_gen_unique_name(str.c_str(), false));
38}
39} // namespace
40
42 if(typeid(*this) == typeid(ordered_semaphore)) {
43 auto diff = static_cast<int>(capacity) - static_cast<int>(c);
44 capacity = c;
45 value -= diff;
46 if(value > 0)
47 free_evt.notify(sc_core::SC_ZERO_TIME);
48 } else {
49 SCCWARN(SCMOD) << "cannot resize fixed size ordered semaphore";
50 }
51}
52
53void ordered_semaphore::trace(sc_core::sc_trace_file* tf) const {
54 if(value_traceable) {
55 value_ref->trace(tf);
56 }
57}
58
59void ordered_semaphore::report_error(const char* id, const char* add_msg) const {
60 auto msg = add_msg ? util::strprintf("semaphore '%s'", name()) : util::strprintf("%s: semaphore '%s'", add_msg, name());
61 SC_REPORT_ERROR(id, msg.c_str());
62}
63
64// constructors
66: sc_core::sc_object(sc_core::sc_gen_unique_name("semaphore"))
67, free_evt(gen_unique_event_name("free_event").c_str())
68, value(init_value_)
69, capacity(init_value_) {
70 if(value < 0) {
71 report_error(sc_core::SC_ID_INVALID_SEMAPHORE_VALUE_);
72 }
73}
74
75ordered_semaphore::ordered_semaphore(const char* name_, unsigned init_value_, bool value_traceable)
76: sc_object(name_)
77, free_evt(gen_unique_event_name("free_event").c_str())
78, value(init_value_)
79, capacity(init_value_)
80, value_traceable(value_traceable) {
81 if(value < 0) {
82 report_error(sc_core::SC_ID_INVALID_SEMAPHORE_VALUE_);
83 }
84 if(value_traceable)
85 value_ref.reset(new scc::sc_ref_variable<int>(std::string(basename()) + "_count", value, true));
86}
87
88// interface methods
89
90// lock (take) the semaphore, block if not available
91auto ordered_semaphore::wait(unsigned priority) -> int {
92 queue.at(priority).push_back(sc_core::sc_get_current_process_handle());
93 while(in_use()) {
94 sc_core::wait(free_evt);
95 }
96 --value;
97 if(value_ref)
98 value_ref->notify();
99 return value;
100}
101
102// lock (take) the semaphore, return -1 if not available
103
105 if(in_use()) {
106 return -1;
107 }
108 --value;
109 if(value_ref)
110 value_ref->notify();
111 return value;
112}
113
114// unlock (give) the semaphore
115
117 if(capacity && value == capacity) {
118 SCCWARN(SCMOD) << "post() called on entirely free semaphore!";
119 } else {
120 ++value;
121 if(value_ref)
122 value_ref->notify();
123 }
124 if(value > 0)
125 free_evt.notify(sc_core::SC_ZERO_TIME);
126 return value;
127}
128
129} // namespace scc
void trace(sc_core::sc_trace_file *tf) const override
adds internal variables to trace
int wait() override
lock (take) the semaphore, block if not available
int trywait() override
lock (take) the semaphore, return -1 if not available
void set_capacity(unsigned capacity)
change the capacity
int post() override
unlock (give) the semaphore
ordered_semaphore(unsigned init_value=1)
constructor of an un-named semaphore
SCC TLM utilities.
SCC common utilities.
Definition bit_field.h:30
std::string strprintf(const std::string format,...)
allocate and print to a string buffer
Definition strprintf.h:35
the sc_ref_variable for a particular plain data type. This marks an existing C++ variable as discover...