2 * yosys -- Yosys Open SYnthesis Suite
4 * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.com>
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 #include "kernel/register.h"
21 #include "kernel/celltypes.h"
22 #include "kernel/sigtools.h"
23 #include "kernel/rtlil.h"
24 #include "kernel/log.h"
27 PRIVATE_NAMESPACE_BEGIN
29 struct dff_map_info_t
{
30 RTLIL::SigSpec sig_d
, sig_clk
, sig_arst
;
31 bool clk_polarity
, arst_polarity
;
32 RTLIL::Const arst_value
;
33 std::vector
<RTLIL::IdString
> cells
;
36 struct dff_map_bit_info_t
{
37 RTLIL::SigBit bit_d
, bit_clk
, bit_arst
;
38 bool clk_polarity
, arst_polarity
;
39 RTLIL::State arst_value
;
43 bool consider_wire(RTLIL::Wire
*wire
, std::map
<RTLIL::IdString
, dff_map_info_t
> &dff_dq_map
)
45 if (wire
->name
[0] == '$' || dff_dq_map
.count(wire
->name
))
52 bool consider_cell(RTLIL::Design
*design
, std::set
<RTLIL::IdString
> &dff_cells
, RTLIL::Cell
*cell
)
54 if (cell
->name
[0] == '$' || dff_cells
.count(cell
->name
))
56 if (cell
->type
[0] == '\\' && (design
->module(cell
->type
) == nullptr))
61 bool compare_wires(RTLIL::Wire
*wire1
, RTLIL::Wire
*wire2
)
63 log_assert(wire1
->name
== wire2
->name
);
64 if (wire1
->width
!= wire2
->width
)
69 bool compare_cells(RTLIL::Cell
*cell1
, RTLIL::Cell
*cell2
)
71 log_assert(cell1
->name
== cell2
->name
);
72 if (cell1
->type
!= cell2
->type
)
74 if (cell1
->parameters
!= cell2
->parameters
)
79 void find_dff_wires(std::set
<RTLIL::IdString
> &dff_wires
, RTLIL::Module
*module
)
82 ct
.setup_internals_mem();
83 ct
.setup_stdcells_mem();
85 SigMap
sigmap(module
);
88 for (auto cell
: module
->cells()) {
89 if (ct
.cell_known(cell
->type
) && cell
->hasPort(ID::Q
))
90 dffsignals
.add(sigmap(cell
->getPort(ID::Q
)));
93 for (auto w
: module
->wires()) {
94 if (dffsignals
.check_any(w
))
95 dff_wires
.insert(w
->name
);
99 void create_dff_dq_map(std::map
<RTLIL::IdString
, dff_map_info_t
> &map
, RTLIL::Module
*module
)
101 std::map
<RTLIL::SigBit
, dff_map_bit_info_t
> bit_info
;
102 SigMap
sigmap(module
);
104 for (auto cell
: module
->selected_cells())
106 dff_map_bit_info_t info
;
107 info
.bit_d
= RTLIL::State::Sm
;
108 info
.bit_clk
= RTLIL::State::Sm
;
109 info
.bit_arst
= RTLIL::State::Sm
;
110 info
.clk_polarity
= false;
111 info
.arst_polarity
= false;
112 info
.arst_value
= RTLIL::State::Sm
;
115 if (info
.cell
->type
== ID($dff
)) {
116 info
.bit_clk
= sigmap(info
.cell
->getPort(ID::CLK
)).as_bit();
117 info
.clk_polarity
= info
.cell
->parameters
.at(ID::CLK_POLARITY
).as_bool();
118 std::vector
<RTLIL::SigBit
> sig_d
= sigmap(info
.cell
->getPort(ID::D
)).to_sigbit_vector();
119 std::vector
<RTLIL::SigBit
> sig_q
= sigmap(info
.cell
->getPort(ID::Q
)).to_sigbit_vector();
120 for (size_t i
= 0; i
< sig_d
.size(); i
++) {
121 info
.bit_d
= sig_d
.at(i
);
122 bit_info
[sig_q
.at(i
)] = info
;
127 if (info
.cell
->type
== ID($adff
)) {
128 info
.bit_clk
= sigmap(info
.cell
->getPort(ID::CLK
)).as_bit();
129 info
.bit_arst
= sigmap(info
.cell
->getPort(ID::ARST
)).as_bit();
130 info
.clk_polarity
= info
.cell
->parameters
.at(ID::CLK_POLARITY
).as_bool();
131 info
.arst_polarity
= info
.cell
->parameters
.at(ID::ARST_POLARITY
).as_bool();
132 std::vector
<RTLIL::SigBit
> sig_d
= sigmap(info
.cell
->getPort(ID::D
)).to_sigbit_vector();
133 std::vector
<RTLIL::SigBit
> sig_q
= sigmap(info
.cell
->getPort(ID::Q
)).to_sigbit_vector();
134 std::vector
<RTLIL::State
> arst_value
= info
.cell
->parameters
.at(ID::ARST_VALUE
).bits
;
135 for (size_t i
= 0; i
< sig_d
.size(); i
++) {
136 info
.bit_d
= sig_d
.at(i
);
137 info
.arst_value
= arst_value
.at(i
);
138 bit_info
[sig_q
.at(i
)] = info
;
143 if (info
.cell
->type
.in(ID($_DFF_N_
), ID($_DFF_P_
))) {
144 info
.bit_clk
= sigmap(info
.cell
->getPort(ID::C
)).as_bit();
145 info
.clk_polarity
= info
.cell
->type
== ID($_DFF_P_
);
146 info
.bit_d
= sigmap(info
.cell
->getPort(ID::D
)).as_bit();
147 bit_info
[sigmap(info
.cell
->getPort(ID::Q
)).as_bit()] = info
;
151 if (info
.cell
->type
.size() == 10 && info
.cell
->type
.begins_with("$_DFF_")) {
152 info
.bit_clk
= sigmap(info
.cell
->getPort(ID::C
)).as_bit();
153 info
.bit_arst
= sigmap(info
.cell
->getPort(ID::R
)).as_bit();
154 info
.clk_polarity
= info
.cell
->type
[6] == 'P';
155 info
.arst_polarity
= info
.cell
->type
[7] == 'P';
156 info
.arst_value
= info
.cell
->type
[0] == '1' ? RTLIL::State::S1
: RTLIL::State::S0
;
157 info
.bit_d
= sigmap(info
.cell
->getPort(ID::D
)).as_bit();
158 bit_info
[sigmap(info
.cell
->getPort(ID::Q
)).as_bit()] = info
;
163 std::map
<RTLIL::IdString
, dff_map_info_t
> empty_dq_map
;
164 for (auto w
: module
->wires())
166 if (!consider_wire(w
, empty_dq_map
))
169 std::vector
<RTLIL::SigBit
> bits_q
= sigmap(w
).to_sigbit_vector();
170 std::vector
<RTLIL::SigBit
> bits_d
;
171 std::vector
<RTLIL::State
> arst_value
;
172 std::set
<RTLIL::Cell
*> cells
;
174 if (bits_q
.empty() || !bit_info
.count(bits_q
.front()))
177 dff_map_bit_info_t ref_info
= bit_info
.at(bits_q
.front());
178 for (auto &bit
: bits_q
) {
179 if (!bit_info
.count(bit
))
181 dff_map_bit_info_t info
= bit_info
.at(bit
);
182 if (info
.bit_clk
!= ref_info
.bit_clk
)
184 if (info
.bit_arst
!= ref_info
.bit_arst
)
186 if (info
.clk_polarity
!= ref_info
.clk_polarity
)
188 if (info
.arst_polarity
!= ref_info
.arst_polarity
)
190 bits_d
.push_back(info
.bit_d
);
191 arst_value
.push_back(info
.arst_value
);
192 cells
.insert(info
.cell
);
195 if (bits_d
.size() != bits_q
.size())
200 info
.sig_clk
= ref_info
.bit_clk
;
201 info
.sig_arst
= ref_info
.bit_arst
;
202 info
.clk_polarity
= ref_info
.clk_polarity
;
203 info
.arst_polarity
= ref_info
.arst_polarity
;
204 info
.arst_value
= arst_value
;
205 for (auto it
: cells
)
206 info
.cells
.push_back(it
->name
);
211 RTLIL::Wire
*add_new_wire(RTLIL::Module
*module
, RTLIL::IdString name
, int width
= 1)
213 if (module
->count_id(name
))
214 log_error("Attempting to create wire %s, but a wire of this name exists already! Hint: Try another value for -sep.\n", log_id(name
));
215 return module
->addWire(name
, width
);
218 struct ExposePass
: public Pass
{
219 ExposePass() : Pass("expose", "convert internal signals to module ports") { }
222 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
224 log(" expose [options] [selection]\n");
226 log("This command exposes all selected internal signals of a module as additional\n");
230 log(" only consider wires that are directly driven by register cell.\n");
233 log(" when exposing a wire, create an input/output pair and cut the internal\n");
234 log(" signal path at that wire.\n");
237 log(" when exposing a wire, create an input port and disconnect the internal\n");
241 log(" only expose those signals that are shared among the selected modules.\n");
242 log(" this is useful for preparing modules for equivalence checking.\n");
245 log(" also turn connections to instances of other modules to additional\n");
246 log(" inputs and outputs and remove the module instances.\n");
248 log(" -evert-dff\n");
249 log(" turn flip-flops to sets of inputs and outputs.\n");
251 log(" -sep <separator>\n");
252 log(" when creating new wire/port names, the original object name is suffixed\n");
253 log(" with this separator (default: '.') and the port name or a type\n");
254 log(" designator for the exposed signal.\n");
257 void execute(std::vector
<std::string
> args
, RTLIL::Design
*design
) override
259 bool flag_shared
= false;
260 bool flag_evert
= false;
261 bool flag_dff
= false;
262 bool flag_cut
= false;
263 bool flag_input
= false;
264 bool flag_evert_dff
= false;
265 std::string sep
= ".";
267 log_header(design
, "Executing EXPOSE pass (exposing internal signals as outputs).\n");
270 for (argidx
= 1; argidx
< args
.size(); argidx
++)
272 if (args
[argidx
] == "-shared") {
276 if (args
[argidx
] == "-evert") {
280 if (args
[argidx
] == "-dff") {
284 if (args
[argidx
] == "-cut") {
286 log_cmd_error("Options -cut and -input are mutually exclusive.\n");
290 if (args
[argidx
] == "-input") {
292 log_cmd_error("Options -cut and -input are mutually exclusive.\n");
296 if (args
[argidx
] == "-evert-dff") {
297 flag_evert_dff
= true;
300 if (args
[argidx
] == "-sep" && argidx
+1 < args
.size()) {
301 sep
= args
[++argidx
];
306 extra_args(args
, argidx
, design
);
308 CellTypes
ct(design
);
310 std::map
<RTLIL::Module
*, std::map
<RTLIL::IdString
, dff_map_info_t
>> dff_dq_maps
;
311 std::map
<RTLIL::Module
*, std::set
<RTLIL::IdString
>> dff_cells
;
315 RTLIL::Module
*first_module
= NULL
;
316 std::set
<RTLIL::IdString
> shared_dff_wires
;
318 for (auto mod
: design
->selected_modules())
320 create_dff_dq_map(dff_dq_maps
[mod
], mod
);
325 if (first_module
== NULL
) {
326 for (auto &it
: dff_dq_maps
[mod
])
327 shared_dff_wires
.insert(it
.first
);
330 std::set
<RTLIL::IdString
> new_shared_dff_wires
;
331 for (auto &it
: shared_dff_wires
) {
332 if (!dff_dq_maps
[mod
].count(it
))
334 if (!compare_wires(first_module
->wire(it
), mod
->wire(it
)))
336 new_shared_dff_wires
.insert(it
);
338 shared_dff_wires
.swap(new_shared_dff_wires
);
343 for (auto &map_it
: dff_dq_maps
)
345 std::map
<RTLIL::IdString
, dff_map_info_t
> new_map
;
346 for (auto &it
: map_it
.second
)
347 if (shared_dff_wires
.count(it
.first
))
348 new_map
[it
.first
] = it
.second
;
349 map_it
.second
.swap(new_map
);
352 for (auto &it1
: dff_dq_maps
)
353 for (auto &it2
: it1
.second
)
354 for (auto &it3
: it2
.second
.cells
)
355 dff_cells
[it1
.first
].insert(it3
);
358 std::set
<RTLIL::IdString
> shared_wires
, shared_cells
;
359 std::set
<RTLIL::IdString
> used_names
;
363 RTLIL::Module
*first_module
= NULL
;
365 for (auto module
: design
->selected_modules())
367 std::set
<RTLIL::IdString
> dff_wires
;
369 find_dff_wires(dff_wires
, module
);
371 if (first_module
== NULL
)
373 for (auto w
: module
->wires())
374 if (design
->selected(module
, w
) && consider_wire(w
, dff_dq_maps
[module
]))
375 if (!flag_dff
|| dff_wires
.count(w
->name
))
376 shared_wires
.insert(w
->name
);
379 for (auto cell
: module
->cells())
380 if (design
->selected(module
, cell
) && consider_cell(design
, dff_cells
[module
], cell
))
381 shared_cells
.insert(cell
->name
);
383 first_module
= module
;
387 std::vector
<RTLIL::IdString
> delete_shared_wires
, delete_shared_cells
;
389 for (auto &it
: shared_wires
)
393 if (module
->wire(it
) == nullptr)
394 goto delete_shared_wire
;
396 wire
= module
->wire(it
);
398 if (!design
->selected(module
, wire
))
399 goto delete_shared_wire
;
400 if (!consider_wire(wire
, dff_dq_maps
[module
]))
401 goto delete_shared_wire
;
402 if (!compare_wires(first_module
->wire(it
), wire
))
403 goto delete_shared_wire
;
404 if (flag_dff
&& !dff_wires
.count(it
))
405 goto delete_shared_wire
;
409 delete_shared_wires
.push_back(it
);
413 for (auto &it
: shared_cells
)
417 if (module
->cell(it
) == nullptr)
418 goto delete_shared_cell
;
420 cell
= module
->cell(it
);
422 if (!design
->selected(module
, cell
))
423 goto delete_shared_cell
;
424 if (!consider_cell(design
, dff_cells
[module
], cell
))
425 goto delete_shared_cell
;
426 if (!compare_cells(first_module
->cell(it
), cell
))
427 goto delete_shared_cell
;
431 delete_shared_cells
.push_back(it
);
434 for (auto &it
: delete_shared_wires
)
435 shared_wires
.erase(it
);
436 for (auto &it
: delete_shared_cells
)
437 shared_cells
.erase(it
);
442 for (auto module
: design
->selected_modules())
444 std::set
<RTLIL::IdString
> dff_wires
;
445 if (flag_dff
&& !flag_shared
)
446 find_dff_wires(dff_wires
, module
);
448 SigMap
sigmap(module
);
450 SigMap out_to_in_map
;
452 std::map
<RTLIL::Wire
*, RTLIL::IdString
> wire_map
;
454 for (auto w
: module
->wires())
457 if (shared_wires
.count(w
->name
) == 0)
460 if (!design
->selected(module
, w
) || !consider_wire(w
, dff_dq_maps
[module
]))
462 if (flag_dff
&& !dff_wires
.count(w
->name
))
468 if (!w
->port_input
) {
469 w
->port_input
= true;
470 log("New module port: %s/%s\n", RTLIL::id2cstr(module
->name
), RTLIL::id2cstr(w
->name
));
471 wire_map
[w
] = NEW_ID
;
476 if (!w
->port_output
) {
477 w
->port_output
= true;
478 log("New module port: %s/%s\n", RTLIL::id2cstr(module
->name
), RTLIL::id2cstr(w
->name
));
482 wire_map
[w
] = w
->name
.str() + sep
+ "i";
489 for (auto &wm
: wire_map
)
491 RTLIL::Wire
*in_wire
= module
->addWire(wm
.second
, GetSize(wm
.first
));
492 out_to_in_map
.add(wm
.first
, in_wire
);
495 for (auto cell
: module
->cells()) {
496 if (!ct
.cell_known(cell
->type
))
498 for (auto &conn
: cell
->connections_
)
499 if (ct
.cell_output(cell
->type
, conn
.first
))
500 conn
.second
= out_to_in_map(sigmap(conn
.second
));
503 for (auto &conn
: module
->connections_
)
504 conn
.first
= out_to_in_map(conn
.first
);
509 for (auto &wm
: wire_map
)
511 RTLIL::Wire
*in_wire
= add_new_wire(module
, wm
.second
, wm
.first
->width
);
512 in_wire
->port_input
= true;
513 out_to_in_map
.add(sigmap(wm
.first
), in_wire
);
516 for (auto cell
: module
->cells()) {
517 if (!ct
.cell_known(cell
->type
))
519 for (auto &conn
: cell
->connections_
)
520 if (ct
.cell_input(cell
->type
, conn
.first
))
521 conn
.second
= out_to_in_map(sigmap(conn
.second
));
524 for (auto &conn
: module
->connections_
)
525 conn
.second
= out_to_in_map(sigmap(conn
.second
));
528 std::set
<RTLIL::SigBit
> set_q_bits
;
530 for (auto &dq
: dff_dq_maps
[module
])
532 if (module
->wire(dq
.first
) == nullptr)
535 RTLIL::Wire
*wire
= module
->wire(dq
.first
);
536 std::set
<RTLIL::SigBit
> wire_bits_set
= sigmap(wire
).to_sigbit_set();
537 std::vector
<RTLIL::SigBit
> wire_bits_vec
= sigmap(wire
).to_sigbit_vector();
539 dff_map_info_t
&info
= dq
.second
;
541 RTLIL::Wire
*wire_dummy_q
= add_new_wire(module
, NEW_ID
, 0);
543 for (auto &cell_name
: info
.cells
) {
544 RTLIL::Cell
*cell
= module
->cell(cell_name
);
545 std::vector
<RTLIL::SigBit
> cell_q_bits
= sigmap(cell
->getPort(ID::Q
)).to_sigbit_vector();
546 for (auto &bit
: cell_q_bits
)
547 if (wire_bits_set
.count(bit
))
548 bit
= RTLIL::SigBit(wire_dummy_q
, wire_dummy_q
->width
++);
549 cell
->setPort(ID::Q
, cell_q_bits
);
552 RTLIL::Wire
*wire_q
= add_new_wire(module
, wire
->name
.str() + sep
+ "q", wire
->width
);
553 wire_q
->port_input
= true;
554 log("New module port: %s/%s\n", RTLIL::id2cstr(module
->name
), RTLIL::id2cstr(wire_q
->name
));
556 RTLIL::SigSig connect_q
;
557 for (size_t i
= 0; i
< wire_bits_vec
.size(); i
++) {
558 if (set_q_bits
.count(wire_bits_vec
[i
]))
560 connect_q
.first
.append(wire_bits_vec
[i
]);
561 connect_q
.second
.append(RTLIL::SigBit(wire_q
, i
));
562 set_q_bits
.insert(wire_bits_vec
[i
]);
564 module
->connect(connect_q
);
566 RTLIL::Wire
*wire_d
= add_new_wire(module
, wire
->name
.str() + sep
+ "d", wire
->width
);
567 wire_d
->port_output
= true;
568 log("New module port: %s/%s\n", RTLIL::id2cstr(module
->name
), RTLIL::id2cstr(wire_d
->name
));
569 module
->connect(RTLIL::SigSig(wire_d
, info
.sig_d
));
571 RTLIL::Wire
*wire_c
= add_new_wire(module
, wire
->name
.str() + sep
+ "c");
572 wire_c
->port_output
= true;
573 log("New module port: %s/%s\n", RTLIL::id2cstr(module
->name
), RTLIL::id2cstr(wire_c
->name
));
574 if (info
.clk_polarity
) {
575 module
->connect(RTLIL::SigSig(wire_c
, info
.sig_clk
));
577 RTLIL::Cell
*c
= module
->addCell(NEW_ID
, ID($
not));
578 c
->parameters
[ID::A_SIGNED
] = 0;
579 c
->parameters
[ID::A_WIDTH
] = 1;
580 c
->parameters
[ID::Y_WIDTH
] = 1;
581 c
->setPort(ID::A
, info
.sig_clk
);
582 c
->setPort(ID::Y
, wire_c
);
585 if (info
.sig_arst
!= RTLIL::State::Sm
)
587 RTLIL::Wire
*wire_r
= add_new_wire(module
, wire
->name
.str() + sep
+ "r");
588 wire_r
->port_output
= true;
589 log("New module port: %s/%s\n", RTLIL::id2cstr(module
->name
), RTLIL::id2cstr(wire_r
->name
));
590 if (info
.arst_polarity
) {
591 module
->connect(RTLIL::SigSig(wire_r
, info
.sig_arst
));
593 RTLIL::Cell
*c
= module
->addCell(NEW_ID
, ID($
not));
594 c
->parameters
[ID::A_SIGNED
] = 0;
595 c
->parameters
[ID::A_WIDTH
] = 1;
596 c
->parameters
[ID::Y_WIDTH
] = 1;
597 c
->setPort(ID::A
, info
.sig_arst
);
598 c
->setPort(ID::Y
, wire_r
);
601 RTLIL::Wire
*wire_v
= add_new_wire(module
, wire
->name
.str() + sep
+ "v", wire
->width
);
602 wire_v
->port_output
= true;
603 log("New module port: %s/%s\n", RTLIL::id2cstr(module
->name
), RTLIL::id2cstr(wire_v
->name
));
604 module
->connect(RTLIL::SigSig(wire_v
, info
.arst_value
));
610 std::vector
<RTLIL::Cell
*> delete_cells
;
612 for (auto cell
: module
->cells())
615 if (shared_cells
.count(cell
->name
) == 0)
618 if (!design
->selected(module
, cell
) || !consider_cell(design
, dff_cells
[module
], cell
))
622 if (design
->module(cell
->type
) != nullptr)
624 RTLIL::Module
*mod
= design
->module(cell
->type
);
626 for (auto p
: mod
->wires())
628 if (!p
->port_input
&& !p
->port_output
)
631 RTLIL::Wire
*w
= add_new_wire(module
, cell
->name
.str() + sep
+ RTLIL::unescape_id(p
->name
), p
->width
);
633 w
->port_output
= true;
635 w
->port_input
= true;
637 log("New module port: %s/%s (%s)\n", RTLIL::id2cstr(module
->name
), RTLIL::id2cstr(w
->name
), RTLIL::id2cstr(cell
->type
));
640 if (cell
->hasPort(p
->name
))
641 sig
= cell
->getPort(p
->name
);
642 sig
.extend_u0(w
->width
);
644 module
->connect(RTLIL::SigSig(sig
, w
));
646 module
->connect(RTLIL::SigSig(w
, sig
));
651 for (auto &it
: cell
->connections())
653 RTLIL::Wire
*w
= add_new_wire(module
, cell
->name
.str() + sep
+ RTLIL::unescape_id(it
.first
), it
.second
.size());
654 if (ct
.cell_input(cell
->type
, it
.first
))
655 w
->port_output
= true;
656 if (ct
.cell_output(cell
->type
, it
.first
))
657 w
->port_input
= true;
659 log("New module port: %s/%s (%s)\n", RTLIL::id2cstr(module
->name
), RTLIL::id2cstr(w
->name
), RTLIL::id2cstr(cell
->type
));
662 module
->connect(RTLIL::SigSig(it
.second
, w
));
664 module
->connect(RTLIL::SigSig(w
, it
.second
));
668 delete_cells
.push_back(cell
);
671 for (auto cell
: delete_cells
) {
672 log("Removing cell: %s/%s (%s)\n", log_id(module
), log_id(cell
), log_id(cell
->type
));
673 module
->remove(cell
);
677 module
->fixup_ports();
682 PRIVATE_NAMESPACE_END