The problem is that you are using multiple non-blocking statements to assign the signal.
sig_2_o0 <= '0';
sig_2_o0 <= '1';
This translates to:
at next event assign '0' to sig_2_o0.
at next event assign '1' to sig_2_o0.
This is different than using blocking assignments:
sig_2_o0 := '0';
sig_2_o0 := '1';
Which would translate to:
assign '0' to sig_2_o0.
assign '1' to sig_2_o0.
Blocking assignments
When you use blocking assignments the value is clearly defined. First it will set to '0', then override it with '1'. In this example there should be no effect from the first blocking assignment for either simulation or synthesized hardware. You can think of it as there is 0 delay between the first assignment and the second. This means you have a pulse of 0 width, which is actually nothing. It is equivalent to having just the last assignment, with the first omitted entirely. One caveat is that if you put a delay on the assignments, e.g. "after 1 ns" then you will notice the first assignment followed by the second in simulation. In hardware, delays are ignored and so there would be no change from adding delays. In fact, inserting delays in RTL that is intended to be synthesized is strongly discouraged for this reason. It is highly desirable that the hardware matches the simulation, and adding delays can introduce mismatches.
Non-blocking assignments
But when you use non-blocking assignments the simulator has two assignments scheduled for the next time event. Set the signal to '1' and at the same time, set it to '0'. So which scheduled assignment will the signal take? There is no way to know. It may be either value since it is incorrectly assigned. Every lint checker and synthesis tool on the planet should throw an error when encountering multiple non-blocking assignments like this. It may be possible to simulate it, but there is clearly a problem with the RTL.