55
66#include < cstdint>
77#include < cstdlib>
8+ #include < map>
9+ #include < string_view>
810#include < utility>
911
1012#include " sta/Liberty.hh"
@@ -31,7 +33,8 @@ void importTargets(Graph& g, sta::Network* network, utl::Logger* logger)
3133 return ;
3234 }
3335
34- // Build expected input/output widths from liberty cell ports.
36+ std::map<std::string_view, uint32_t > lib_input_offset;
37+ std::map<std::string_view, uint32_t > lib_output_offset;
3538 uint32_t lib_input_width = 0 ;
3639 uint32_t lib_output_width = 0 ;
3740 sta::LibertyCellPortIterator port_iter (cell);
@@ -42,10 +45,14 @@ void importTargets(Graph& g, sta::Network* network, utl::Logger* logger)
4245 }
4346 sta::PortDirection* dir = port->direction ();
4447 if (dir->isInput ()) {
48+ lib_input_offset[port->name ()] = lib_input_width;
4549 lib_input_width += port->size ();
4650 } else if (dir->isOutput ()) {
51+ lib_output_offset[port->name ()] = lib_output_width;
4752 lib_output_width += port->size ();
4853 } else if (dir->isBidirect ()) {
54+ lib_input_offset[port->name ()] = lib_input_width;
55+ lib_output_offset[port->name ()] = lib_output_width;
4956 lib_input_width += port->size ();
5057 lib_output_width += port->size ();
5158 }
@@ -66,8 +73,7 @@ void importTargets(Graph& g, sta::Network* network, utl::Logger* logger)
6673 logger->error (utl::SYN ,
6774 10 ,
6875 " importTargets: cell '{}' input width mismatch:"
69- " Other has {} bits, Liberty has {} bits. This is an "
70- " internal tool error." ,
76+ " Verilog instantiation has {} bits, Liberty has {} bits." ,
7177 other->cellType (),
7278 other_input_width,
7379 lib_input_width);
@@ -77,26 +83,89 @@ void importTargets(Graph& g, sta::Network* network, utl::Logger* logger)
7783 logger->error (utl::SYN ,
7884 11 ,
7985 " importTargets: cell '{}' output width mismatch:"
80- " Other has {} bits, Liberty has {} bits. This is an "
81- " internal tool error." ,
86+ " Verilog instantiation has {} bits, Liberty has {} bits." ,
8287 other->cellType (),
8388 other_output_width,
8489 lib_output_width);
8590 }
8691
8792 // Concatenate all input port values into a single Bundle.
88- Bundle inputs;
93+ Bundle inputs = Bundle::sentinel (lib_input_width) ;
8994 for (auto & port : other->ports ()) {
9095 if (port.direction == Other::Port::kInput
9196 || port.direction == Other::Port::kInOut ) {
92- inputs = inputs.concat (port.value );
97+ sta::LibertyPort* lib_port = cell->findLibertyPort (port.name );
98+ if (!lib_port || !lib_input_offset.contains (port.name )) {
99+ logger->error (
100+ utl::SYN ,
101+ 35 ,
102+ " importTargets: cell '{}' Liberty definition is missing "
103+ " port '{}' connected in Verilog instantiation." ,
104+ other->cellType (),
105+ port.name );
106+ }
107+
108+ if (((uint32_t ) lib_port->size ()) != port.width ) {
109+ logger->error (
110+ utl::SYN ,
111+ 36 ,
112+ " importTargets: cell '{}' instantiated with mismatched width "
113+ " of port '{}': {} in Verilog vs {} in Liberty" ,
114+ other->cellType (),
115+ port.name ,
116+ port.width ,
117+ lib_port->size ());
118+ }
119+
120+ uint32_t offset = lib_input_offset.at (port.name );
121+ for (uint32_t i = 0 ; i < port.width ; i++) {
122+ inputs.mutableNet (offset + i) = port.value [i];
123+ }
93124 }
94125 }
95126
96127 // Create Target and replace outputs.
97128 BundleView old_output = g.output (other);
98- Bundle new_output = g.add <Target>(cell, std::move (inputs));
99- g.forceReplace (old_output, BundleView (new_output));
129+ Bundle target_output = g.add <Target>(cell, std::move (inputs));
130+ Bundle output_replacement = Bundle::sentinel (lib_output_width);
131+
132+ uint32_t offset = 0 ;
133+ for (auto & port : other->ports ()) {
134+ if (port.direction == Other::Port::kOutput
135+ || port.direction == Other::Port::kInOut ) {
136+ sta::LibertyPort* lib_port = cell->findLibertyPort (port.name );
137+ if (!lib_port || !lib_output_offset.contains (port.name )) {
138+ logger->error (
139+ utl::SYN ,
140+ 37 ,
141+ " importTargets: cell '{}' Liberty definition is missing "
142+ " port '{}' connected in Verilog instantiation." ,
143+ other->cellType (),
144+ port.name );
145+ }
146+
147+ if (((uint32_t ) lib_port->size ()) != port.width ) {
148+ logger->error (
149+ utl::SYN ,
150+ 38 ,
151+ " importTargets: cell '{}' instantiated with mismatched width "
152+ " of port '{}': {} in Verilog vs {} in Liberty" ,
153+ other->cellType (),
154+ port.name ,
155+ port.width ,
156+ lib_port->size ());
157+ }
158+
159+ uint32_t lib_offset = lib_output_offset.at (port.name );
160+ for (uint32_t i = 0 ; i < port.width ; i++) {
161+ output_replacement.mutableNet (offset + i)
162+ = target_output[lib_offset + i];
163+ }
164+ offset += port.width ;
165+ }
166+ }
167+
168+ g.forceReplace (old_output, BundleView (output_replacement));
100169 g.removeInstance (
101170 const_cast <Instance*>(static_cast <const Instance*>(other)));
102171 });
0 commit comments