mirror of
https://github.com/YosysHQ/yosys
synced 2025-05-06 15:25:47 +00:00
Merge remote-tracking branch 'origin/master' into xc7dsp
This commit is contained in:
commit
e3d898dccb
49 changed files with 1136 additions and 554 deletions
|
@ -325,6 +325,8 @@ Aig::Aig(Cell *cell)
|
|||
int A = mk.inport("\\A", i);
|
||||
int B = mk.inport("\\B", i);
|
||||
int Y = mk.mux_gate(A, B, S);
|
||||
if (cell->type == "$_NMUX_")
|
||||
Y = mk.not_gate(Y);
|
||||
mk.outport(Y, "\\Y", i);
|
||||
}
|
||||
goto optimize;
|
||||
|
|
|
@ -193,6 +193,7 @@ struct CellTypes
|
|||
setup_type("$_ANDNOT_", {A, B}, {Y}, true);
|
||||
setup_type("$_ORNOT_", {A, B}, {Y}, true);
|
||||
setup_type("$_MUX_", {A, B, S}, {Y}, true);
|
||||
setup_type("$_NMUX_", {A, B, S}, {Y}, true);
|
||||
setup_type("$_MUX4_", {A, B, C, D, S, T}, {Y}, true);
|
||||
setup_type("$_MUX8_", {A, B, C, D, E, F, G, H, S, T, U}, {Y}, true);
|
||||
setup_type("$_MUX16_", {A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, S, T, U, V}, {Y}, true);
|
||||
|
|
|
@ -145,7 +145,7 @@ struct ConstEval
|
|||
if (cell->hasPort("\\B"))
|
||||
sig_b = cell->getPort("\\B");
|
||||
|
||||
if (cell->type == "$mux" || cell->type == "$pmux" || cell->type == "$_MUX_")
|
||||
if (cell->type.in("$mux", "$pmux", "$_MUX_", "$_NMUX_"))
|
||||
{
|
||||
std::vector<RTLIL::SigSpec> y_candidates;
|
||||
int count_maybe_set_s_bits = 0;
|
||||
|
@ -175,7 +175,10 @@ struct ConstEval
|
|||
for (auto &yc : y_candidates) {
|
||||
if (!eval(yc, undef, cell))
|
||||
return false;
|
||||
y_values.push_back(yc.as_const());
|
||||
if (cell->type == "$_NMUX_")
|
||||
y_values.push_back(RTLIL::const_not(yc.as_const(), Const(), false, false, GetSize(yc)));
|
||||
else
|
||||
y_values.push_back(yc.as_const());
|
||||
}
|
||||
|
||||
if (y_values.size() > 1)
|
||||
|
|
134
kernel/cost.h
134
kernel/cost.h
|
@ -24,62 +24,92 @@
|
|||
|
||||
YOSYS_NAMESPACE_BEGIN
|
||||
|
||||
int get_cell_cost(RTLIL::Cell *cell, dict<RTLIL::IdString, int> *mod_cost_cache = nullptr);
|
||||
|
||||
inline int get_cell_cost(RTLIL::IdString type, const dict<RTLIL::IdString, RTLIL::Const> ¶meters = dict<RTLIL::IdString, RTLIL::Const>(),
|
||||
RTLIL::Design *design = nullptr, dict<RTLIL::IdString, int> *mod_cost_cache = nullptr)
|
||||
struct CellCosts
|
||||
{
|
||||
static dict<RTLIL::IdString, int> gate_cost = {
|
||||
{ "$_BUF_", 1 },
|
||||
{ "$_NOT_", 2 },
|
||||
{ "$_AND_", 4 },
|
||||
{ "$_NAND_", 4 },
|
||||
{ "$_OR_", 4 },
|
||||
{ "$_NOR_", 4 },
|
||||
{ "$_ANDNOT_", 4 },
|
||||
{ "$_ORNOT_", 4 },
|
||||
{ "$_XOR_", 8 },
|
||||
{ "$_XNOR_", 8 },
|
||||
{ "$_AOI3_", 6 },
|
||||
{ "$_OAI3_", 6 },
|
||||
{ "$_AOI4_", 8 },
|
||||
{ "$_OAI4_", 8 },
|
||||
{ "$_MUX_", 4 }
|
||||
};
|
||||
|
||||
if (gate_cost.count(type))
|
||||
return gate_cost.at(type);
|
||||
|
||||
if (parameters.empty() && design && design->module(type))
|
||||
{
|
||||
RTLIL::Module *mod = design->module(type);
|
||||
|
||||
if (mod->attributes.count("\\cost"))
|
||||
return mod->attributes.at("\\cost").as_int();
|
||||
|
||||
dict<RTLIL::IdString, int> local_mod_cost_cache;
|
||||
if (mod_cost_cache == nullptr)
|
||||
mod_cost_cache = &local_mod_cost_cache;
|
||||
|
||||
if (mod_cost_cache->count(mod->name))
|
||||
return mod_cost_cache->at(mod->name);
|
||||
|
||||
int module_cost = 1;
|
||||
for (auto c : mod->cells())
|
||||
module_cost += get_cell_cost(c, mod_cost_cache);
|
||||
|
||||
(*mod_cost_cache)[mod->name] = module_cost;
|
||||
return module_cost;
|
||||
static const dict<RTLIL::IdString, int>& default_gate_cost() {
|
||||
static const dict<RTLIL::IdString, int> db = {
|
||||
{ "$_BUF_", 1 },
|
||||
{ "$_NOT_", 2 },
|
||||
{ "$_AND_", 4 },
|
||||
{ "$_NAND_", 4 },
|
||||
{ "$_OR_", 4 },
|
||||
{ "$_NOR_", 4 },
|
||||
{ "$_ANDNOT_", 4 },
|
||||
{ "$_ORNOT_", 4 },
|
||||
{ "$_XOR_", 5 },
|
||||
{ "$_XNOR_", 5 },
|
||||
{ "$_AOI3_", 6 },
|
||||
{ "$_OAI3_", 6 },
|
||||
{ "$_AOI4_", 7 },
|
||||
{ "$_OAI4_", 7 },
|
||||
{ "$_MUX_", 4 },
|
||||
{ "$_NMUX_", 4 }
|
||||
};
|
||||
return db;
|
||||
}
|
||||
|
||||
log_warning("Can't determine cost of %s cell (%d parameters).\n", log_id(type), GetSize(parameters));
|
||||
return 1;
|
||||
}
|
||||
static const dict<RTLIL::IdString, int>& cmos_gate_cost() {
|
||||
static const dict<RTLIL::IdString, int> db = {
|
||||
{ "$_BUF_", 1 },
|
||||
{ "$_NOT_", 2 },
|
||||
{ "$_AND_", 6 },
|
||||
{ "$_NAND_", 4 },
|
||||
{ "$_OR_", 6 },
|
||||
{ "$_NOR_", 4 },
|
||||
{ "$_ANDNOT_", 6 },
|
||||
{ "$_ORNOT_", 6 },
|
||||
{ "$_XOR_", 12 },
|
||||
{ "$_XNOR_", 12 },
|
||||
{ "$_AOI3_", 6 },
|
||||
{ "$_OAI3_", 6 },
|
||||
{ "$_AOI4_", 8 },
|
||||
{ "$_OAI4_", 8 },
|
||||
{ "$_MUX_", 12 },
|
||||
{ "$_NMUX_", 10 }
|
||||
};
|
||||
return db;
|
||||
}
|
||||
|
||||
inline int get_cell_cost(RTLIL::Cell *cell, dict<RTLIL::IdString, int> *mod_cost_cache)
|
||||
{
|
||||
return get_cell_cost(cell->type, cell->parameters, cell->module->design, mod_cost_cache);
|
||||
}
|
||||
dict<RTLIL::IdString, int> mod_cost_cache;
|
||||
const dict<RTLIL::IdString, int> *gate_cost = nullptr;
|
||||
Design *design = nullptr;
|
||||
|
||||
int get(RTLIL::IdString type) const
|
||||
{
|
||||
if (gate_cost && gate_cost->count(type))
|
||||
return gate_cost->at(type);
|
||||
|
||||
log_warning("Can't determine cost of %s cell.\n", log_id(type));
|
||||
return 1;
|
||||
}
|
||||
|
||||
int get(RTLIL::Cell *cell)
|
||||
{
|
||||
if (gate_cost && gate_cost->count(cell->type))
|
||||
return gate_cost->at(cell->type);
|
||||
|
||||
if (design && design->module(cell->type) && cell->parameters.empty())
|
||||
{
|
||||
RTLIL::Module *mod = design->module(cell->type);
|
||||
|
||||
if (mod->attributes.count("\\cost"))
|
||||
return mod->attributes.at("\\cost").as_int();
|
||||
|
||||
if (mod_cost_cache.count(mod->name))
|
||||
return mod_cost_cache.at(mod->name);
|
||||
|
||||
int module_cost = 1;
|
||||
for (auto c : mod->cells())
|
||||
module_cost += get(c);
|
||||
|
||||
mod_cost_cache[mod->name] = module_cost;
|
||||
return module_cost;
|
||||
}
|
||||
|
||||
log_warning("Can't determine cost of %s cell (%d parameters).\n", log_id(cell->type), GetSize(cell->parameters));
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
|
||||
YOSYS_NAMESPACE_END
|
||||
|
||||
|
|
|
@ -522,6 +522,12 @@ int main(int argc, char **argv)
|
|||
if (!backend_command.empty())
|
||||
run_backend(output_filename, backend_command);
|
||||
|
||||
yosys_design->check();
|
||||
for (auto it : saved_designs)
|
||||
it.second->check();
|
||||
for (auto it : pushed_designs)
|
||||
it->check();
|
||||
|
||||
if (!depsfile.empty())
|
||||
{
|
||||
FILE *f = fopen(depsfile.c_str(), "wt");
|
||||
|
|
|
@ -41,6 +41,45 @@ void decompress_gzip(const std::string &filename, std::stringstream &out)
|
|||
}
|
||||
gzclose(gzf);
|
||||
}
|
||||
|
||||
/*
|
||||
An output stream that uses a stringbuf to buffer data internally,
|
||||
using zlib to write gzip-compressed data every time the stream is flushed.
|
||||
*/
|
||||
class gzip_ostream : public std::ostream {
|
||||
public:
|
||||
gzip_ostream()
|
||||
{
|
||||
rdbuf(&outbuf);
|
||||
}
|
||||
bool open(const std::string &filename)
|
||||
{
|
||||
return outbuf.open(filename);
|
||||
}
|
||||
private:
|
||||
class gzip_streambuf : public std::stringbuf {
|
||||
public:
|
||||
gzip_streambuf() { };
|
||||
bool open(const std::string &filename)
|
||||
{
|
||||
gzf = gzopen(filename.c_str(), "wb");
|
||||
return gzf != nullptr;
|
||||
}
|
||||
virtual int sync() override
|
||||
{
|
||||
gzwrite(gzf, reinterpret_cast<const void *>(str().c_str()), unsigned(str().size()));
|
||||
str("");
|
||||
return 0;
|
||||
}
|
||||
~gzip_streambuf()
|
||||
{
|
||||
sync();
|
||||
gzclose(gzf);
|
||||
}
|
||||
private:
|
||||
gzFile gzf = nullptr;
|
||||
} outbuf;
|
||||
};
|
||||
PRIVATE_NAMESPACE_END
|
||||
|
||||
#endif
|
||||
|
@ -256,8 +295,6 @@ void Pass::call(RTLIL::Design *design, std::vector<std::string> args)
|
|||
pass_register[args[0]]->post_execute(state);
|
||||
while (design->selection_stack.size() > orig_sel_stack_pos)
|
||||
design->selection_stack.pop_back();
|
||||
|
||||
design->check();
|
||||
}
|
||||
|
||||
void Pass::call_on_selection(RTLIL::Design *design, const RTLIL::Selection &selection, std::string command)
|
||||
|
@ -339,8 +376,10 @@ void ScriptPass::run(std::string command, std::string info)
|
|||
log(" %s\n", command.c_str());
|
||||
else
|
||||
log(" %s %s\n", command.c_str(), info.c_str());
|
||||
} else
|
||||
} else {
|
||||
Pass::call(active_design, command);
|
||||
active_design->check();
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptPass::run_script(RTLIL::Design *design, std::string run_from, std::string run_to)
|
||||
|
@ -534,8 +573,6 @@ void Frontend::frontend_call(RTLIL::Design *design, std::istream *f, std::string
|
|||
args.push_back(filename);
|
||||
frontend_register[args[0]]->execute(args, design);
|
||||
}
|
||||
|
||||
design->check();
|
||||
}
|
||||
|
||||
Backend::Backend(std::string name, std::string short_help) :
|
||||
|
@ -588,14 +625,28 @@ void Backend::extra_args(std::ostream *&f, std::string &filename, std::vector<st
|
|||
|
||||
filename = arg;
|
||||
rewrite_filename(filename);
|
||||
std::ofstream *ff = new std::ofstream;
|
||||
ff->open(filename.c_str(), std::ofstream::trunc);
|
||||
yosys_output_files.insert(filename);
|
||||
if (ff->fail()) {
|
||||
delete ff;
|
||||
log_cmd_error("Can't open output file `%s' for writing: %s\n", filename.c_str(), strerror(errno));
|
||||
if (filename.size() > 3 && filename.substr(filename.size()-3) == ".gz") {
|
||||
#ifdef YOSYS_ENABLE_ZLIB
|
||||
gzip_ostream *gf = new gzip_ostream;
|
||||
if (!gf->open(filename)) {
|
||||
delete gf;
|
||||
log_cmd_error("Can't open output file `%s' for writing: %s\n", filename.c_str(), strerror(errno));
|
||||
}
|
||||
yosys_output_files.insert(filename);
|
||||
f = gf;
|
||||
#else
|
||||
log_cmd_error("Yosys is compiled without zlib support, unable to write gzip output.\n");
|
||||
#endif
|
||||
} else {
|
||||
std::ofstream *ff = new std::ofstream;
|
||||
ff->open(filename.c_str(), std::ofstream::trunc);
|
||||
yosys_output_files.insert(filename);
|
||||
if (ff->fail()) {
|
||||
delete ff;
|
||||
log_cmd_error("Can't open output file `%s' for writing: %s\n", filename.c_str(), strerror(errno));
|
||||
}
|
||||
f = ff;
|
||||
}
|
||||
f = ff;
|
||||
}
|
||||
|
||||
if (called_with_fp)
|
||||
|
@ -645,8 +696,6 @@ void Backend::backend_call(RTLIL::Design *design, std::ostream *f, std::string f
|
|||
|
||||
while (design->selection_stack.size() > orig_sel_stack_pos)
|
||||
design->selection_stack.pop_back();
|
||||
|
||||
design->check();
|
||||
}
|
||||
|
||||
static struct CellHelpMessages {
|
||||
|
|
|
@ -1249,6 +1249,7 @@ namespace {
|
|||
if (cell->type == "$_ANDNOT_") { check_gate("ABY"); return; }
|
||||
if (cell->type == "$_ORNOT_") { check_gate("ABY"); return; }
|
||||
if (cell->type == "$_MUX_") { check_gate("ABSY"); return; }
|
||||
if (cell->type == "$_NMUX_") { check_gate("ABSY"); return; }
|
||||
if (cell->type == "$_AOI3_") { check_gate("ABCY"); return; }
|
||||
if (cell->type == "$_OAI3_") { check_gate("ABCY"); return; }
|
||||
if (cell->type == "$_AOI4_") { check_gate("ABCDY"); return; }
|
||||
|
@ -1976,6 +1977,7 @@ DEF_METHOD_3(XnorGate, "$_XNOR_", A, B, Y)
|
|||
DEF_METHOD_3(AndnotGate, "$_ANDNOT_", A, B, Y)
|
||||
DEF_METHOD_3(OrnotGate, "$_ORNOT_", A, B, Y)
|
||||
DEF_METHOD_4(MuxGate, "$_MUX_", A, B, S, Y)
|
||||
DEF_METHOD_4(NmuxGate, "$_NMUX_", A, B, S, Y)
|
||||
DEF_METHOD_4(Aoi3Gate, "$_AOI3_", A, B, C, Y)
|
||||
DEF_METHOD_4(Oai3Gate, "$_OAI3_", A, B, C, Y)
|
||||
DEF_METHOD_5(Aoi4Gate, "$_AOI4_", A, B, C, D, Y)
|
||||
|
@ -3354,13 +3356,7 @@ RTLIL::SigSpec RTLIL::SigSpec::extract(int offset, int length) const
|
|||
{
|
||||
unpack();
|
||||
cover("kernel.rtlil.sigspec.extract_pos");
|
||||
auto it = bits_.begin() + std::min<int>(offset, width_);
|
||||
decltype(it) ie;
|
||||
if (length >= 0)
|
||||
ie = bits_.begin() + std::min<int>(offset + length, width_);
|
||||
else
|
||||
ie = bits_.end() + std::max<int>(length + 1, offset - width_);
|
||||
return std::vector<RTLIL::SigBit>(it, ie);
|
||||
return std::vector<RTLIL::SigBit>(bits_.begin() + offset, bits_.begin() + offset + length);
|
||||
}
|
||||
|
||||
void RTLIL::SigSpec::append(const RTLIL::SigSpec &signal)
|
||||
|
|
|
@ -788,6 +788,7 @@ public:
|
|||
RTLIL::SigSpec extract(const RTLIL::SigSpec &pattern, const RTLIL::SigSpec *other = NULL) const;
|
||||
RTLIL::SigSpec extract(const pool<RTLIL::SigBit> &pattern, const RTLIL::SigSpec *other = NULL) const;
|
||||
RTLIL::SigSpec extract(int offset, int length = 1) const;
|
||||
RTLIL::SigSpec extract_end(int offset) const { return extract(offset, width_ - offset); }
|
||||
|
||||
void append(const RTLIL::SigSpec &signal);
|
||||
void append_bit(const RTLIL::SigBit &bit);
|
||||
|
@ -1155,6 +1156,7 @@ public:
|
|||
RTLIL::Cell* addAndnotGate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_y, const std::string &src = "");
|
||||
RTLIL::Cell* addOrnotGate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_y, const std::string &src = "");
|
||||
RTLIL::Cell* addMuxGate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_s, RTLIL::SigBit sig_y, const std::string &src = "");
|
||||
RTLIL::Cell* addNmuxGate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_s, RTLIL::SigBit sig_y, const std::string &src = "");
|
||||
RTLIL::Cell* addAoi3Gate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_c, RTLIL::SigBit sig_y, const std::string &src = "");
|
||||
RTLIL::Cell* addOai3Gate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_c, RTLIL::SigBit sig_y, const std::string &src = "");
|
||||
RTLIL::Cell* addAoi4Gate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_c, RTLIL::SigBit sig_d, RTLIL::SigBit sig_y, const std::string &src = "");
|
||||
|
@ -1230,6 +1232,7 @@ public:
|
|||
RTLIL::SigBit AndnotGate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, const std::string &src = "");
|
||||
RTLIL::SigBit OrnotGate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, const std::string &src = "");
|
||||
RTLIL::SigBit MuxGate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_s, const std::string &src = "");
|
||||
RTLIL::SigBit NmuxGate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_s, const std::string &src = "");
|
||||
RTLIL::SigBit Aoi3Gate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_c, const std::string &src = "");
|
||||
RTLIL::SigBit Oai3Gate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_c, const std::string &src = "");
|
||||
RTLIL::SigBit Aoi4Gate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_c, RTLIL::SigBit sig_d, const std::string &src = "");
|
||||
|
|
|
@ -475,7 +475,7 @@ struct SatGen
|
|||
return true;
|
||||
}
|
||||
|
||||
if (cell->type == "$_MUX_" || cell->type == "$mux")
|
||||
if (cell->type == "$_MUX_" || cell->type == "$mux" || cell->type == "$_NMUX_")
|
||||
{
|
||||
std::vector<int> a = importDefSigSpec(cell->getPort("\\A"), timestep);
|
||||
std::vector<int> b = importDefSigSpec(cell->getPort("\\B"), timestep);
|
||||
|
@ -483,7 +483,10 @@ struct SatGen
|
|||
std::vector<int> y = importDefSigSpec(cell->getPort("\\Y"), timestep);
|
||||
|
||||
std::vector<int> yy = model_undef ? ez->vec_var(y.size()) : y;
|
||||
ez->assume(ez->vec_eq(ez->vec_ite(s.at(0), b, a), yy));
|
||||
if (cell->type == "$_NMUX_")
|
||||
ez->assume(ez->vec_eq(ez->vec_not(ez->vec_ite(s.at(0), b, a)), yy));
|
||||
else
|
||||
ez->assume(ez->vec_eq(ez->vec_ite(s.at(0), b, a), yy));
|
||||
|
||||
if (model_undef)
|
||||
{
|
||||
|
|
|
@ -964,14 +964,18 @@ void run_frontend(std::string filename, std::string command, std::string *backen
|
|||
command += next_line;
|
||||
}
|
||||
handle_label(command, from_to_active, run_from, run_to);
|
||||
if (from_to_active)
|
||||
if (from_to_active) {
|
||||
Pass::call(design, command);
|
||||
design->check();
|
||||
}
|
||||
}
|
||||
|
||||
if (!command.empty()) {
|
||||
handle_label(command, from_to_active, run_from, run_to);
|
||||
if (from_to_active)
|
||||
if (from_to_active) {
|
||||
Pass::call(design, command);
|
||||
design->check();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (...) {
|
||||
|
@ -1000,6 +1004,7 @@ void run_frontend(std::string filename, std::string command, std::string *backen
|
|||
Pass::call(design, vector<string>({command, filename}));
|
||||
else
|
||||
Frontend::frontend_call(design, NULL, filename, command);
|
||||
design->check();
|
||||
}
|
||||
|
||||
void run_frontend(std::string filename, std::string command, RTLIL::Design *design)
|
||||
|
@ -1183,6 +1188,7 @@ void shell(RTLIL::Design *design)
|
|||
design->selection_stack.pop_back();
|
||||
log_reset_stack();
|
||||
}
|
||||
design->check();
|
||||
}
|
||||
if (command == NULL)
|
||||
printf("exit\n");
|
||||
|
|
|
@ -88,6 +88,10 @@ extern int Tcl_EvalFile(Tcl_Interp *interp, const char *fileName);
|
|||
extern void Tcl_Finalize(void);
|
||||
extern int Tcl_GetCommandInfo(Tcl_Interp *interp, const char *cmdName, Tcl_CmdInfo *infoPtr);
|
||||
extern const char *Tcl_GetStringResult(Tcl_Interp *interp);
|
||||
extern Tcl_Obj *Tcl_NewStringObj(const char *bytes, int length);
|
||||
extern Tcl_Obj *Tcl_NewIntObj(int intValue);
|
||||
extern Tcl_Obj *Tcl_NewListObj(int objc, Tcl_Obj *const objv[]);
|
||||
extern Tcl_Obj *Tcl_ObjSetVar2(Tcl_Interp *interp, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, Tcl_Obj *newValuePtr, int flags);
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue