Skip to content

Commit cc6fe77

Browse files
committed
pln blif-checker: initial support for MOGs
1 parent 7ddad22 commit cc6fe77

File tree

3 files changed

+202
-17
lines changed

3 files changed

+202
-17
lines changed

stars/src/file_readers/pln_blif_file.cpp

Lines changed: 176 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,15 @@ void BLIF_file::reset(CStr nm, uint16_t tr) noexcept {
2222
err_msg_.clear();
2323
}
2424

25+
// "model "
26+
static inline bool starts_w_model(CStr z, size_t len) noexcept {
27+
assert(z);
28+
if (len < 6)
29+
return false;
30+
return z[0] == 'm' and z[1] == 'o' and z[2] == 'd' and
31+
z[3] == 'e' and z[4] == 'l' and ::isspace(z[5]);
32+
}
33+
2534
// "inputs "
2635
static inline bool starts_w_inputs(CStr z, size_t len) noexcept {
2736
assert(z);
@@ -78,6 +87,18 @@ static inline bool starts_w_R_eq(CStr z) noexcept {
7887
return z[0] == 'R' and z[1] == '=';
7988
}
8089

90+
// "T="
91+
static inline bool starts_w_T_eq(CStr z) noexcept {
92+
assert(z);
93+
if (::strlen(z) < 2)
94+
return false;
95+
return z[0] == 'T' and z[1] == '=';
96+
}
97+
98+
static inline bool starts_w_R_or_T(CStr z) noexcept {
99+
return starts_w_R_eq(z) or starts_w_T_eq(z);
100+
}
101+
81102
// "I="
82103
static inline bool starts_w_I_eq(CStr z) noexcept {
83104
assert(z);
@@ -86,6 +107,30 @@ static inline bool starts_w_I_eq(CStr z) noexcept {
86107
return z[0] == 'I' and z[1] == '=';
87108
}
88109

110+
// "O="
111+
static inline bool starts_w_O_eq(CStr z) noexcept {
112+
assert(z);
113+
if (::strlen(z) < 2)
114+
return false;
115+
return z[0] == 'O' and z[1] == '=';
116+
}
117+
118+
// "Y="
119+
static inline bool starts_w_Y_eq(CStr z) noexcept {
120+
assert(z);
121+
if (::strlen(z) < 2)
122+
return false;
123+
return z[0] == 'Y' and z[1] == '=';
124+
}
125+
126+
// "Q="
127+
static inline bool starts_w_Q_eq(CStr z) noexcept {
128+
assert(z);
129+
if (::strlen(z) < 2)
130+
return false;
131+
return z[0] == 'Q' and z[1] == '=';
132+
}
133+
89134
// sometimes in eblif the gate output is not the last token. correct it.
90135
static void place_output_at_back(vector<string>& dat) noexcept {
91136
size_t dsz = dat.size();
@@ -113,7 +158,7 @@ bool BLIF_file::readBlif() noexcept {
113158
if (ts) {
114159
int tr = ::atoi(ts);
115160
if (tr > 0) {
116-
tr = std::max(tr, 1000);
161+
tr = std::min(tr, 1000);
117162
trace_ = tr;
118163
}
119164
}
@@ -169,6 +214,9 @@ bool BLIF_file::readBlif() noexcept {
169214
lprintf(" ....\\ ... num_escaped= %zu\n", num_escaped);
170215
}
171216

217+
std::vector<string> V; // tmp buffer for tokenizing
218+
V.reserve(16);
219+
172220
inputs_lnum_ = outputs_lnum_ = 0;
173221
err_lnum_ = 0;
174222
for (size_t i = 1; i < lsz; i++) {
@@ -187,19 +235,26 @@ bool BLIF_file::readBlif() noexcept {
187235
outputs_lnum_ = i;
188236
continue;
189237
}
190-
if (inputs_lnum_ and outputs_lnum_) break;
238+
if (starts_w_model(cs + 1, len - 1)) {
239+
V.clear();
240+
Fio::split_spa(cs, V);
241+
if (V.size() > 1)
242+
topModel_ = V.back();
243+
}
244+
if (inputs_lnum_ and outputs_lnum_)
245+
break;
191246
}
192247
if (!inputs_lnum_ and !outputs_lnum_) {
193248
err_msg_ = ".inputs/.outputs not found";
194249
return false;
195250
}
196251

197252
if (trace_ >= 3) {
253+
lprintf("\t .... topModel_= %s\n", topModel_.c_str());
198254
lprintf("\t .... inputs_lnum_= %zu outputs_lnum_= %zu\n", inputs_lnum_, outputs_lnum_);
199255
}
200256

201-
std::vector<string> V;
202-
V.reserve(16);
257+
V.clear();
203258
if (inputs_lnum_) {
204259
Fio::split_spa(lines_[inputs_lnum_], V);
205260
if (V.size() > 1 and V.front() == ".inputs") {
@@ -355,10 +410,10 @@ uint BLIF_file::printNodes(std::ostream& os) const noexcept {
355410
for (uint i = 1; i <= n; i++) {
356411
const Node& nd = nodePool_[i];
357412
os_printf(os,
358-
" |%u| L:%u %s inDeg=%u outDeg=%u par=%u out:%s ",
413+
" |%u| L:%u %s inDeg=%u outDeg=%u par=%u out:%s mog:%i/%i ",
359414
i, nd.lnum_, nd.kw_.c_str(),
360415
nd.inDeg(), nd.outDeg(), nd.parent_,
361-
nd.cOut());
416+
nd.cOut(), nd.isMog(), nd.isVirtualMog());
362417
if (nd.data_.empty()) {
363418
os << endl;
364419
} else {
@@ -373,6 +428,69 @@ uint BLIF_file::printNodes(std::ostream& os) const noexcept {
373428
return n;
374429
}
375430

431+
static bool s_is_MOG(const vector<string>& data,
432+
vector<string>& terms) noexcept {
433+
terms.clear();
434+
uint dsz = data.size();
435+
assert(dsz < 1000000);
436+
if (dsz < 4)
437+
return false;
438+
439+
bool has_O = false, has_Y = false, has_Q = false;
440+
uint sum = 0;
441+
442+
for (uint i = dsz - 1; i > 1; i--) {
443+
CStr cs = data[i].c_str();
444+
if (!has_O) {
445+
has_O = starts_w_O_eq(cs);
446+
if (has_O)
447+
terms.emplace_back(cs);
448+
}
449+
if (!has_Y) {
450+
has_Y = starts_w_Y_eq(cs);
451+
if (has_Y)
452+
terms.emplace_back(cs);
453+
}
454+
if (!has_Q) {
455+
has_Q = starts_w_Q_eq(cs);
456+
if (has_Q)
457+
terms.emplace_back(cs);
458+
}
459+
sum = uint(has_O) + uint(has_Y) + uint(has_Q);
460+
if (sum == 3)
461+
break;
462+
}
463+
464+
sum = uint(has_O) + uint(has_Y) + uint(has_Q);
465+
if (sum < 2) {
466+
terms.clear();
467+
return false;
468+
}
469+
return true;
470+
}
471+
472+
static void s_remove_MOG_terms(vector<string>& data) noexcept {
473+
uint dsz = data.size();
474+
assert(dsz < 1000000);
475+
if (dsz < 4)
476+
return;
477+
for (uint i = dsz - 1; i > 1; i--) {
478+
CStr cs = data[i].c_str();
479+
if (starts_w_O_eq(cs)) {
480+
data.erase(data.begin() + i);
481+
continue;
482+
}
483+
if (starts_w_Y_eq(cs)) {
484+
data.erase(data.begin() + i);
485+
continue;
486+
}
487+
if (starts_w_Q_eq(cs)) {
488+
data.erase(data.begin() + i);
489+
continue;
490+
}
491+
}
492+
}
493+
376494
bool BLIF_file::createNodes() noexcept {
377495
nodePool_.clear();
378496
topInputs_.clear();
@@ -460,6 +578,55 @@ bool BLIF_file::createNodes() noexcept {
460578
return false;
461579
}
462580

581+
// -- replace MOGs by virtual SOGs
582+
num_MOGs_ = 0;
583+
for (uint i = 1; i <= nn; i++) {
584+
V.clear();
585+
Node& nd = nodePool_[i];
586+
if (nd.kw_ != ".subckt" and nd.kw_ != ".gate")
587+
continue;
588+
if (nd.data_.size() < 4)
589+
continue;
590+
if (nd.is_IBUF() or nd.is_OBUF())
591+
continue;
592+
assert(!nd.is_mog_);
593+
594+
// if (topModel_ == "MOG_01" and i == 10)
595+
// lputs9();
596+
597+
s_is_MOG(nd.data_, V);
598+
bool is_mog = V.size() > 1;
599+
if (is_mog) {
600+
if (trace_ >= 5) {
601+
lprintf("\t\t .... MOG-type: %s\n", nd.cType());
602+
lprintf("\t\t .... [terms] V.size()= %zu\n", V.size());
603+
logVec(V, " [V-terms] ");
604+
lputs();
605+
}
606+
607+
s_remove_MOG_terms(nd.data_);
608+
uint startVirtual = nodePool_.size();
609+
for (uint j = 1; j < V.size(); j++) {
610+
nodePool_.emplace_back(nd);
611+
nodePool_.back().virtualOrigin_ = i;
612+
nodePool_.back().is_mog_ = true;
613+
}
614+
nd.data_.push_back(V.front());
615+
nd.is_mog_ = true;
616+
// give one output term to each virtual MOG:
617+
uint V_index = 1;
618+
for (uint k = startVirtual; k < nodePool_.size(); k++) {
619+
assert(V_index < V.size());
620+
Node& k_node = nodePool_[k];
621+
k_node.data_.push_back(V[V_index++]);
622+
}
623+
num_MOGs_++;
624+
}
625+
}
626+
627+
nn = numNodes();
628+
assert(nn);
629+
463630
fabricNodes_.reserve(nn);
464631

465632
// -- finish and index nodes:
@@ -681,8 +848,8 @@ bool BLIF_file::linkNodes() noexcept {
681848
assert(pinIndex >= 0);
682849
assert(uint(pinIndex) < par->data_.size());
683850
const string& pinToken = par->data_[pinIndex];
684-
if (not starts_w_R_eq(pinToken.c_str())) {
685-
// skipping reset pins "R="
851+
if (not starts_w_R_or_T(pinToken.c_str())) {
852+
// skipping reset (and similar) pins "R=", "T="
686853
// because they can be both input and output.
687854
// need to read library primitives to determine direction.
688855
err_msg_ = "output port contacts fabric input: ";
@@ -736,8 +903,6 @@ bool BLIF_file::linkNodes() noexcept {
736903
}
737904

738905
// 4. every node except topInputs_ should be driven
739-
/*
740-
///// --- not ready - need to support multi-driver cells
741906
string inp1;
742907
for (Node* fab_nd : fabricNodes_) {
743908
Node& nd = *fab_nd;
@@ -752,7 +917,7 @@ bool BLIF_file::linkNodes() noexcept {
752917
continue;
753918
Node* drv_cell = findFabricDriver(nd.id_, inp1);
754919
if (!drv_cell) {
755-
lputs9();
920+
// lputs9();
756921
err_msg_ = "undriven cell input: ";
757922
err_msg_ += inp1;
758923
if (trace_ >= 2) {
@@ -763,7 +928,6 @@ bool BLIF_file::linkNodes() noexcept {
763928
return false;
764929
}
765930
}
766-
*/
767931

768932
return true;
769933
}

stars/src/file_readers/pln_blif_file.h

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,18 @@ struct BLIF_file : public fio::MMapReader
2323

2424
string kw_; // keyword: .names, .subckt, etc.
2525
vector<string> data_; // everything on the line ater kw, tokenized
26-
string out_; // usually last token in 'data_'
2726

28-
int16_t is_top_ = 0; // -1 : top input
29-
// 1 : top output
27+
// vector<string> mog_outs_; // pin names O, Y, Q are considered to be outputs.
28+
// // MOG-nodes are transformed to bunches of SOG-nodes.
3029

30+
string out_; // SOG output (real or virtual)
31+
32+
uint virtualOrigin_ = 0; // node-ID from which this virtual MOG is created
33+
34+
int16_t is_top_ = 0; // -1:top input 1:top output
35+
bool is_mog_ = false;
36+
37+
public:
3138
Node() noexcept = default;
3239
Node(CStr keyword, uint L) noexcept : lnum_(L) {
3340
if (keyword) kw_ = keyword;
@@ -40,6 +47,9 @@ struct BLIF_file : public fio::MMapReader
4047
bool isRoot() const noexcept { return parent_ == 0; }
4148
bool isLeaf() const noexcept { return chld_.empty(); }
4249

50+
bool isMog() const noexcept { return is_mog_; }
51+
bool isVirtualMog() const noexcept { return is_mog_ and virtualOrigin_ > 0; }
52+
4353
bool valid() const noexcept { return id_ > 0; }
4454
void inval() noexcept { id_ = 0; }
4555

@@ -56,16 +66,26 @@ struct BLIF_file : public fio::MMapReader
5666
// returns pin index in chld_ or -1
5767
int in_contact(const string& x) const noexcept;
5868

69+
bool is_IBUF() const noexcept {
70+
return data_.size() > 1 and data_.front() == "I_BUF";
71+
}
72+
bool is_OBUF() const noexcept {
73+
return data_.size() > 1 and data_.front() == "O_BUF";
74+
}
75+
5976
string firstInputPin() const noexcept;
6077

6178
CStr cOut() const noexcept { return out_.empty() ? "{e}" : out_.c_str(); }
79+
CStr cType() const noexcept { return data_.empty() ? "{e}" : data_.front().c_str(); }
6280

6381
struct CmpOut {
6482
bool operator()(const Node* a, const Node* b) const noexcept {
6583
return a->out_ < b->out_;
6684
}
6785
};
68-
};
86+
}; // Node
87+
88+
string topModel_;
6989

7090
vector<string> inputs_;
7191
vector<string> outputs_;
@@ -77,6 +97,7 @@ struct BLIF_file : public fio::MMapReader
7797

7898
bool rd_ok_ = false;
7999
bool chk_ok_ = false;
100+
uint num_MOGs_ = 0;
80101

81102
public:
82103
BLIF_file() noexcept = default;

stars/src/main.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
static const char* _pln_VERSION_STR = "pln0221";
1+
static const char* _pln_VERSION_STR = "pln0222";
22

33
#include "RS/rsEnv.h"
44
#include "util/pln_log.h"

0 commit comments

Comments
 (0)