diff options
author | Mike Jones <mjjones@us.ibm.com> | 2011-11-17 19:38:31 -0600 |
---|---|---|
committer | MIKE J. JONES <mjjones@us.ibm.com> | 2011-11-21 12:07:50 -0600 |
commit | 11c80c5abcf203e5a65098ea047fd6d2a6e607cc (patch) | |
tree | 1e1a5246e8ed0b25b66e6e1e34bba7622f63bbea /src/usr/hwpf/ifcompiler/initScom.C | |
parent | b9d93e82a069b6650f3bd7b43abe6aecc0bf2e4e (diff) | |
download | blackbird-hostboot-11c80c5abcf203e5a65098ea047fd6d2a6e607cc.tar.gz blackbird-hostboot-11c80c5abcf203e5a65098ea047fd6d2a6e607cc.zip |
HWPF: Only support initfile attributes in fapiGetInitFileAttr()
Change-Id: Ia1ffa854d55b68f0e32595080bba323cd52e23a3
Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/503
Tested-by: Jenkins Server
Reviewed-by: Andrew J. Geissler <andrewg@us.ibm.com>
Reviewed-by: CAMVAN T. NGUYEN <ctnguyen@us.ibm.com>
Reviewed-by: A. Patrick Williams III <iawillia@us.ibm.com>
Diffstat (limited to 'src/usr/hwpf/ifcompiler/initScom.C')
-rwxr-xr-x | src/usr/hwpf/ifcompiler/initScom.C | 1372 |
1 files changed, 1372 insertions, 0 deletions
diff --git a/src/usr/hwpf/ifcompiler/initScom.C b/src/usr/hwpf/ifcompiler/initScom.C new file mode 100755 index 000000000..b37c05182 --- /dev/null +++ b/src/usr/hwpf/ifcompiler/initScom.C @@ -0,0 +1,1372 @@ +// IBM_PROLOG_BEGIN_TAG +// This is an automatically generated prolog. +// +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/ifcompiler/initScom.C,v $ +// +// IBM CONFIDENTIAL +// +// COPYRIGHT International Business Machines Corp. 2010,2010 +// +//UNDEFINED +// +// Origin: UNDEFINED +// +// IBM_PROLOG_END_TAG + +// Change Log ************************************************************************************* +// +// Flag Track Userid Date Description +// ----- -------- -------- -------- ------------------------------------------------------------- +// D754106 dgilbert 06/14/10 Create +// dg001 D774126 dgilbert 09/30/10 Check that colname EXPR is last column in spytable +// dg002 SW039868 dgilbert 10/15/10 Add support to filter unneeded inits by EC +// dg003 SW047506 dgilbert 12/09/10 More filtering enhancements +// andrewg 05/24/11 Port over for VPL/PgP +// andrewg 09/19/11 Updates based on review +// andrewg 11/09/11 Multi-dimensional array and move to common fapi include +// mjjones 11/17/11 Output attribute listing +// End Change Log ********************************************************************************* + +/** + * @file initSpy.C + * @brief Definition of the initScom Class. Represents the information parsed from an initfile scom + * statement. + */ + +#include <initScom.H> +#include <initSymbols.H> +#include <initCompiler.H> +#include <stdlib.h> +#include <iostream> +#include <iomanip> +#include <sstream> +#include <fstream> +#include <set> +#include <stdexcept> + +extern void yyerror(const char * s); +extern init::ScomList * yyscomlist; // only use this during parsing + +namespace init { +extern ostringstream dbg; // debug output +}; + +using namespace init; + +Scom::WHEN_SUBTYPE_MAP Scom::cv_when_subtypes; + +//------------------------------------------------------------------------------------------------- + +Scom::Scom(BINSEQ::const_iterator & bli, Symbols * i_symbols): + iv_symbols(i_symbols), + iv_when(NONE), + iv_scom_length(0), + iv_scom_offset(0), + iv_when_rpn(i_symbols) + +{ + + iv_scom_length = Rpn::extract16(bli); + iv_scom_offset = Rpn::extract16(bli); + uint32_t id = Rpn::extract16(bli); + uint32_t numcols = Rpn::extract16(bli); + uint32_t numrows = Rpn::extract16(bli); + + numcols &= ~SUBTYPE_MASK; + + // Get our SCOM address + uint32_t l_addr_size = 0; + iv_scom_addr_hex = iv_symbols->get_numeric_data(iv_symbols->get_rpn_id(id),l_addr_size); + + + if( iv_scom_length != 0 && iv_scom_length != 0xffff) // most common values + { + if(iv_scom_length < 65) // max scom len is 64 bits + { + for(size_t i = 0; i < numrows; ++i) + add_bit_range(iv_scom_offset, iv_scom_offset + iv_scom_length - 1); + } + else // What's this? + { + ostringstream errs; + errs << "ERROR: Invalid scom bit length [" << iv_scom_length << "]" << endl; + throw range_error(errs.str()); + } + } + + for(size_t i = 0; i < numrows; ++i) + { + Rpn rpn(bli,iv_symbols); + iv_scom_rpn.push_back(rpn); + } + + if(numcols) + { + for(size_t i = 0; i < numrows; ++i) iv_row_rpn.push_back(Rpn(iv_symbols)); // blank RPNs + + // Read col heads + for(size_t i = 0; i < numcols; ++i) + { + uint32_t var_tag = Rpn::extract16(bli); + Rpn col_name_rpn(iv_symbols); + col_name_rpn.append(iv_symbols->get_rpn_id(var_tag)); + iv_col_vars.push_back(col_name_rpn); + iv_cols_rpn.push_back(iv_row_rpn); // copy in blank row RPNs for this column + } + + for(size_t row_n = 0; row_n < numrows; ++row_n) + { + COL_LIST::iterator cli = iv_cols_rpn.begin(); // *cli is list of row rpns for col + RPN_LIST::iterator rpi = (*cli).begin() + row_n; // *rpi is current row rpn for first col + BINSEQ::const_iterator bli_end = bli + (*bli); // end of rpn in bin seq + ++bli; ++bli_end; // adjust for first byte being len + // The next len bytes belong to this row + // Simple cols are divided by OPs + // LIST op has two additional bytes (len,op) + while(bli < bli_end) + { + // Last col rpn is not limited to one op if it's "expr" - it gets the rest of the RPN + if(cli == (iv_cols_rpn.end() - 1)) + { + while(bli < bli_end) bli = rpi->bin_read_one_op(bli); + break; + } + bli = rpi->bin_read_one_op(bli); + ++cli; + rpi = (*cli).begin() + row_n; + } + } + } + else ++bli; +} + +//------------------------------------------------------------------------------------------------- + +void Scom::set_when(const string * when_str) +{ + + string s(*when_str); + for(string::iterator c = s.begin(); c != s.end(); ++c) *c = toupper(*c); + if(s.size()) + { + size_t i = 0; + for(size_t i = 1; i < sizeof(when_char)/sizeof(when_char[0]); ++i) + { + if(s[0] == when_char[i]) + { + set_when((SCOM_WHEN)i); + break; + } + } + if(i == sizeof(when_char)/sizeof(when_char[0])) + { + string errs("Illegal when="); + errs.append(s); + yyerror(errs.c_str()); + } + s.erase(0,1); + + if(s.size()) + { + WHEN_SUBTYPE_MAP::const_iterator i = cv_when_subtypes.find(s); + if(i != cv_when_subtypes.end()) + { + set_sub_when(i->second); + } + else + { + std::ostringstream oss; + oss << "Illegal 'when=' subvalue: [" << s << ']'; + yyerror(oss.str().c_str()); + } + } + } + else + { + yyerror("Missing 'when =' value"); + } +} + +//------------------------------------------------------------------------------------------------- + +void Scom::add_col(const string & i_colname) +{ + string s(i_colname); + for(string::iterator i = s.begin(); i != s.end(); ++i) *i = toupper(*i); + Rpn col_rpn(s,iv_symbols); // = iv_symbols->use_symbol(s); + + // add check - Can't add any more cols after EXPR column dg001a + if(iv_col_vars.size() && s != "EXPR") + { + Rpn exp_rpn("EXPR",iv_symbols); + if(exp_rpn == iv_col_vars.back()) // expr col already added - can't add any more cols + { + yyerror("EXPR must be the last column"); + } + } + + // if the entire column is unconditionally true it can be left out + // This check will be done later as this scom might be split by bit-ranges. + + iv_col_vars.push_back(col_rpn); + iv_cols_rpn.push_back(iv_row_rpn); // add the collected row RPNs + iv_row_rpn.clear(); +} + +//------------------------------------------------------------------------------------------------- + +void Scom::add_row_rpn(Rpn * i_rpn) +{ + // The row gets parsed before the col name + // So collect the row RPNs and apply them when the col name gets added + + // Replace the Rpn "ANY" EQ with TRUE dg003a + Rpn any_rpn("ANY",iv_symbols); + Rpn true_rpn(iv_symbols); + true_rpn.push_op(TRUE_OP); + + // The column EXPR can have an lone "ANY" rpn - so add EQ. + if(any_rpn == (*i_rpn)) i_rpn->push_op(EQ); + any_rpn.push_op(EQ); + + if(any_rpn == (*i_rpn)) iv_row_rpn.push_back(true_rpn); // Replace col == ANY with TRUE + else + { + iv_row_rpn.push_back(*i_rpn); + } + delete i_rpn; +} + +//------------------------------------------------------------------------------------------------- + +void Scom::add_bit_range(uint32_t start, uint32_t end) +{ + // make sure they are added in order + dbg << "Add bit range " << start << " to " << end; + iv_range_list.push_back(RANGE(start,end)); +} + +//------------------------------------------------------------------------------------------------- +// Range gets parsed before the target symbol (k,n,p,c) - so save it +void Scom::add_target_range(uint32_t r1, uint32_t r2) +{ + if(r1 > r2) + { + uint32_t rt = r1; + r1 = r2; + r2 = rt; + } + iv_target_ranges.push_back(RANGE(r1,r2)); +} + +//------------------------------------------------------------------------------------------------- + +void Scom::make_target(const char * i_symbol) +{ + string s(i_symbol); + Rpn r(iv_symbols); + size_t rsize = iv_target_ranges.size(); + + if(rsize == 0) + { + yyerror("Target given w/o a range"); + } + // if more than one target - use list + else + { + for(RANGE_LIST::iterator iter = iv_target_ranges.begin(); iter != iv_target_ranges.end(); ++iter) + { + for(uint32_t v = iter->first; v <= iter->second; ++v) + { + r.push_int(v); + } + } + if(rsize > 1) r.push_op(LIST); // if more than one target + r.push_op(EQ); + } + + iv_row_rpn.push_back(r); + add_col(s); + iv_target_ranges.clear(); +} + +//------------------------------------------------------------------------------------------------- + +string Scom::list_one(RANGE range) +{ + ostringstream oss; + + uint32_t numcols = iv_col_vars.size() | (iv_when & SUBTYPE_MASK); // WHEN subtype goes in numcols + uint32_t bitlen = range.second + 1 - range.first; + if (bitlen) + { + iv_scom_length = bitlen; // don't overwrite iv_scom_length if bitlen == 0 + iv_scom_offset = range.first; // don't overwrite iv_scom_offset if bitlen == 0 + } + + uint32_t allrows = 0; + uint32_t numrows = 0; + + if(iv_cols_rpn.size()) allrows = iv_cols_rpn.front().size(); + if (allrows == 0) allrows = 1; + + // If there is a bit range we need to select only the rows that apply to this spyname + if(bitlen) + { + for(RANGE_LIST::iterator r = iv_range_list.begin(); r != iv_range_list.end(); ++r) + { + if((*r) == range) ++numrows; + } + } + else numrows = allrows; // else select all the rows + + oss << hex << setfill('0'); + oss << "------------"; + oss << " Scom Address: 0x" << setw(16) << iv_scom_addr_hex; + if(bitlen) + { + oss << '~' << dec << range.first; + if(range.first != range.second) oss << ':' << range.second; + oss << hex; + } + oss << ' ' << "------------" << endl + << "When= " << (iv_when & WHEN_MASK) << endl; + + oss << "0x" << setw(4) << iv_scom_length << "\t\t" << "Scom length" << endl + << "0x" << setw(4) << iv_scom_offset << "\t\t" << "Scom offset" << endl; + + //oss << "0x" << setw(8) << iv_symbols->get_spy_id(spyname) << '\t'; + + oss << "0x" << setw(4) << numcols << "\t\t" << "Number of columns" << endl + << "0x" << setw(4) << numrows << "\t\t" << "Number of rows" << endl; + + // If there is a bit range we need to select only the spyv rows that apply to this spyname + + if(bitlen) + { + RPN_LIST::iterator i = iv_scom_rpn.begin(); + for(RANGE_LIST::iterator r = iv_range_list.begin(); r != iv_range_list.end(); ++r,++i) + { + if ((*r) == range) + { + oss << i->listing("Length of rpn for spyv",Rpn::cv_empty_str,true); + } + } + } + else // get all rows + { + for(RPN_LIST::iterator i = iv_scom_rpn.begin(); i != iv_scom_rpn.end(); ++i) + { + oss << i->listing("Length of rpn for spyv",Rpn::cv_empty_str,true); + } + } + oss << endl; + + + // list the column names that are really CINI VARS + for(RPN_LIST::iterator i = iv_col_vars.begin(); i != iv_col_vars.end(); ++i) + { + oss << i->listing("",Rpn::cv_empty_str,true); + //Rpn col_rpn = *i; + //string desc = iv_symbols->find_name(rpn_id); + //if(desc.size() == 0) desc = "Variable not found!"; + + //oss << "0x" << setw(4) << iv_symbols->get_tag(*i) << "\t\t" << desc << endl; + } + oss << endl << endl; + + + + uint32_t usedrows = 0; + if(iv_cols_rpn.size() == 0) + { + oss << "ROW " << 1 << "\n0x00" << "\t\t" << "0 BYTES" << endl; + } + else + { + for(size_t n = 0; n < allrows; ++n) + { + Rpn rpn(iv_symbols); + if(bitlen) // only get rows that match the current bitrange + { + if(iv_range_list[n] != range) continue; + } + ++usedrows; + oss << "ROW " << usedrows << endl; + + // Build up the row Rpn for row n + for(COL_LIST::iterator i = iv_cols_rpn.begin(); i != iv_cols_rpn.end(); ++i) + { + rpn.append(i->at(n)); + } + oss << rpn.listing(NULL,Rpn::cv_empty_str,true) << endl; + } + } + + return oss.str(); +} + +//------------------------------------------------------------------------------------------------- + +string Scom::listing() +{ + ostringstream oss; + + set<RANGE> ranges; + ranges.insert(iv_range_list.begin(),iv_range_list.end()); + + //oss << list_one(RANGE(1,0)) << endl; + if(ranges.size()) + { + for(set<RANGE>::iterator r = ranges.begin(); r != ranges.end(); ++r) + { + oss << list_one(*r) << endl; + } + } + else + { + oss << list_one(RANGE(1,0)) << endl; + } + + return oss.str(); +} + +//------------------------------------------------------------------------------------------------- + +uint32_t Scom::bin_listing(BINSEQ & blist) +{ + set<RANGE> ranges; + uint32_t scom_count = 0; + + row_optimize(); // delete any rows that are unconditionally false. + merge rows + + ranges.insert(iv_range_list.begin(),iv_range_list.end()); + + SCOM_ADDR::iterator i = iv_scom_addr.begin(); + // if more than one spyname, the first is just the stem of the name - skip it + if(iv_scom_addr.size() > 1) ++i; + + for(; i != iv_scom_addr.end(); ++i) + { + //printf("scom address:%s\n",(*i).c_str()); + if(ranges.size()) + { + for(set<RANGE>::iterator r = ranges.begin(); r != ranges.end(); ++r) + { + ++scom_count; + //bin_list_one(blist,*i,*r); + // The following sequence will optimize the bytecode for this spy + // - Compile the spy into bytecode for a range of bits + // - Recreate the spy from the bytecode + // - Compile the recreated spy back into bytecode. + BINSEQ temp; + bin_list_one(temp,strtoul((*i).c_str(),NULL,16), *r); + BINSEQ::const_iterator bi = temp.begin(); + Scom s(bi,iv_symbols); + s.bin_list_one(blist,strtoul((*i).c_str(),NULL,16), RANGE(1,0)); + } + } + else + { + ++scom_count; + bin_list_one(blist,strtoul((*i).c_str(),NULL,16), RANGE(1,0)); + } + } + + return scom_count; +} + +//------------------------------------------------------------------------------------------------- + +void Scom::bin_list_one(BINSEQ & blist,uint64_t i_addr, RANGE range) +{ + + uint32_t numcols = iv_col_vars.size() | (iv_when & SUBTYPE_MASK); // WHEN subtype goes in numcols + +// No range support + uint32_t bitlen = range.second + 1 - range.first; + + if (bitlen) + { + iv_scom_length = bitlen; // don't overwrite iv_scom_length if bitlen == 0 + iv_scom_offset = range.first; // don't overwrite iv_scom_offset if bitlen == 0 + } + + uint32_t allrows = 0; + uint32_t numrows = 0; + + if(iv_cols_rpn.size()) allrows = iv_cols_rpn.front().size(); + if (allrows == 0) allrows = 1; + + // If there is a bit range we need to select only the rows that apply to this spyname + if(bitlen) + { + for(RANGE_LIST::iterator r = iv_range_list.begin(); r != iv_range_list.end(); ++r) + { + if((*r) == range) ++numrows; + } + } + else numrows = allrows; // else select all the rows + + // If every row rpn in a column is unconditionally true then remove the col. + if(iv_col_vars.size()) + { + vector< pair<RPN_LIST::iterator, COL_LIST::iterator> > deletes; + RPN_LIST::iterator cv = iv_col_vars.begin(); // -> column header Rpn + COL_LIST::iterator cr = iv_cols_rpn.begin(); // -> RPN list of row segments for the column + for(; cv != iv_col_vars.end(); ++cv,++cr) + { + bool remove_it = true; + for(RPN_LIST::const_iterator r = cr->begin(); r != cr->end(); ++r) + { + if(!(r->isTrue())) + { + remove_it = false; + break; + } + } + if(remove_it) + { + deletes.push_back( pair<RPN_LIST::iterator, COL_LIST::iterator>(cv,cr) ); + } + } + while(deletes.size()) + { + pair<RPN_LIST::iterator, COL_LIST::iterator> p = deletes.back(); + deletes.pop_back(); + dbg << "COL is unconditionally true. Removing column " << (p.first)->symbol_names() + << endl; + iv_col_vars.erase(p.first); + iv_cols_rpn.erase(p.second); + --numcols; + } + } + + Rpn::set16(blist,(uint16_t)iv_scom_length); + Rpn::set16(blist,(uint16_t)iv_scom_offset); + + // Just put the SCOM address in place of the spy id + //uint32_t id = iv_symbols->get_spy_id(spyname); + //Rpn::set32(blist,id); + // TODO - Probably need to get scom address id here + //Rpn::set32(blist,(uint32_t)iv_address); + + Rpn *l_scom_addr = new init::Rpn(i_addr,yyscomlist->get_symbols()); + l_scom_addr->bin_str(blist,false); + delete l_scom_addr; + + + Rpn::set16(blist,(uint16_t)numcols); + Rpn::set16(blist,(uint16_t)numrows); + + // If there is a bit range we need to select only the spyv rows that apply to this spyname + if(bitlen) + { + RPN_LIST::iterator i = iv_scom_rpn.begin(); + for(RANGE_LIST::iterator r = iv_range_list.begin(); r != iv_range_list.end(); ++r,++i) + { + if ((*r) == range) + { + i->bin_str(blist,false); + } + } + } + else // get all rows + { + for(RPN_LIST::iterator i = iv_scom_rpn.begin(); i != iv_scom_rpn.end(); ++i) + { + i->bin_str(blist,false); + } + } + + // list the column names that are really CINI VARS + for(RPN_LIST::iterator i = iv_col_vars.begin(); i != iv_col_vars.end(); ++i) + { + i->bin_str(blist,false); // false means don't prepend an RPN byte count to the binary rpn appended. + //uint16_t tag = iv_symbols->get_tag(*i); + //blist.push_back((uint8_t)(tag >> 8)); + //blist.push_back((uint8_t) tag); + } + + if(iv_cols_rpn.size() == 0) blist.push_back(0); + else + { + for(size_t n = 0; n < allrows; ++n) + { + Rpn rpn(iv_symbols); + if(bitlen) // only get rows that match the current bitrange + { + if(iv_range_list[n] != range) continue; + } + + // Build up the row Rpn for row n + for(COL_LIST::iterator i = iv_cols_rpn.begin(); i != iv_cols_rpn.end(); ++i) + { + rpn.append(i->at(n)); + } + rpn.bin_str(blist,true); + } + } +} + +//------------------------------------------------------------------------------------------------- +// Delete any rows that are unconditionally false +// Merge rows that can be merged +// +void Scom::row_optimize() //dg003a +{ + size_t row = 0; + if (iv_cols_rpn.size()) row = iv_cols_rpn.front().size(); + if(row == 0) return; + + // Look for false rows + do + { + bool remove_me = false; + --row; + for(COL_LIST::iterator i = iv_cols_rpn.begin(); i != iv_cols_rpn.end(); ++i) + { + if (i->at(row).isFalse()) + { + remove_me = true; + break; + } + } + if(remove_me) + { + iv_scom_rpn.erase(iv_scom_rpn.begin() + row); //remove spyv + //Need to remove rpn row segment from each iv_cols_rpn rpn list + for(COL_LIST::iterator i = iv_cols_rpn.begin(); i != iv_cols_rpn.end(); ++i) + { + i->erase(i->begin() + row); + } + if(iv_range_list.size()) iv_range_list.erase(iv_range_list.begin() + row); + + //dbg << "ROW is unconditionally false. Removing row " << row+1 << " from " << get_key_name() << endl; + } + } while (row); + + // now look for rows to merge + // for now limit to spies with EXPR as the only column + // Because the interpreter looks down the rows until it finds one that's "true" then stops, the order + // of rows cant't be modified. This means only rows next to each other can be merged. + // This makes for very large Rpn strings - turn on later when we have better redundancy reduction in RPNs +#if defined(__LATER__) + Rpn r_expr("EXPR", iv_symbols); + row = iv_spyv_rpn.size(); + if ((row > 1) && (iv_col_vars.size() == 1) && (iv_col_vars.front() == r_expr)) + { + --row; + do + { + size_t row1 = row - 1; + + if (iv_spyv_rpn.at(row) == iv_spyv_rpn.at(row1)) + { + if (iv_range_list.size() == 0 || (iv_range_list.at(row) == iv_range_list.at(row1))) + { + // merge + Rpn * rp = new Rpn(iv_cols_rpn.back().at(row)); + iv_cols_rpn.back().at(row1).push_merge(rp, Rpn::OR); // this will delete rp + iv_spyv_rpn.erase(iv_spyv_rpn.begin() + row); + if (iv_range_list.size()) iv_range_list.erase(iv_range_list.begin() + row); + for (COL_LIST::iterator i = iv_cols_rpn.begin(); i != iv_cols_rpn.end(); ++i) + { + i->erase(i->begin() + row); + } + dbg << "ROW " << row+1 << " and " << row1+1 << " have been merged in " << get_key_name() << endl; + } + } + } while (--row); + } +#endif +} + + + +//------------------------------------------------------------------------------------------------- + +bool Scom::compare(Scom & that) +{ + bool result = false; //true; +// TODO +#if 0 + ostringstream oss; + oss << hex << setfill('0'); + // spyname(s) should have already been tested + oss << get_key_name() << endl; + if(iv_spy_type != that.iv_spy_type || + iv_when != that.iv_when || + iv_spy_length != that.iv_spy_length || + iv_spy_offset != that.iv_spy_offset || + iv_array_addr != that.iv_array_addr) + { + result = false; + oss << "type: " << setw(8) << iv_spy_type << ' ' << that.iv_spy_type << endl; + oss << "when: " << setw(8) << iv_when << ' ' << that.iv_when << endl; + oss << "len: " << setw(8) << iv_spy_length << ' ' << that.iv_spy_length << endl; + oss << "offset: " << setw(8) << iv_spy_offset << ' ' << that.iv_spy_offset << endl; + oss << "array: " << setw(8) << iv_array_addr << ' ' << that.iv_array_addr << endl; + } + // need to expand all Rpns to verify resolution of vars and lits + // when Rpn + string rpn1 = iv_when_rpn.listing("",iv_spy_names.front(),false); + string rpn2 = that.iv_when_rpn.listing("",iv_spy_names.front(),false); + if(rpn1 != rpn2) + { + result = false; + oss << "this when Rpn:" << endl << rpn1 << endl; + oss << "that when Rpn:" << endl << rpn2 << endl; + } + + // spyv Rpn + if(iv_spyv_rpn.size() != that.iv_spyv_rpn.size()) + { + result = false; + oss << "this spyv Rpn(s):" << endl; + for(RPN_LIST::iterator r1 = iv_spyv_rpn.begin(); r1 != iv_spyv_rpn.end(); ++r1) + oss << r1->listing("",iv_spy_names.front(),false) << endl; + oss << "that spyv Rpn(s):" << endl; + for(RPN_LIST::iterator r1 = that.iv_spyv_rpn.begin(); r1 != that.iv_spyv_rpn.end(); ++r1) + oss << r1->listing("",iv_spy_names.front(),false) << endl; + } + else + { + RPN_LIST::iterator r1 = iv_spyv_rpn.begin(); + RPN_LIST::iterator r2 = that.iv_spyv_rpn.begin(); + for(; r1 != iv_spyv_rpn.end(); ++r1, ++r2) + { + rpn1 = r1->listing("",iv_spy_names.front(),false); + rpn2 = r2->listing("",iv_spy_names.front(),false); + if(rpn1 != rpn2) + { + result = false; + oss << "this spyv Rpn:" << endl << rpn1 << endl; + oss << "that spyv Rpn:" << endl << rpn2 << endl; + } + } + } + + // column names + if(iv_col_vars.size() != that.iv_col_vars.size()) + { + result = false; + oss << "this col names:" << endl; + for(RPN_LIST::iterator i = iv_col_vars.begin(); i != iv_col_vars.end(); ++i) + { + oss << i->symbol_names() << endl; + } + oss << "that col names:" << endl; + for(RPN_LIST::iterator i = that.iv_col_vars.begin(); i != that.iv_col_vars.end(); ++i) + { + oss << i->symbol_names() << endl; + } + } + else + { + RPN_LIST::iterator i = iv_col_vars.begin(); + RPN_LIST::iterator j = that.iv_col_vars.begin(); + for(;i != iv_col_vars.end(); ++i, ++j) + { + //string s1 = iv_symbols->find_name(*i); + //string s2 = that.iv_symbols->find_name(*j); + if((*i) != (*j)) + { + result = false; + oss << "this col name: " << i->symbol_names() << endl; + oss << "that col name: " << j->symbol_names() << endl; + } + } + } + + // row Rpns + Rpn r1(iv_symbols); + Rpn r2(that.iv_symbols); + for(COL_LIST::iterator c = iv_cols_rpn.begin(); c != iv_cols_rpn.end(); ++c) + { + for(RPN_LIST::iterator r = c->begin(); r != c->end(); ++r) + { + r1.append(*r); + } + } + for(COL_LIST::iterator c = that.iv_cols_rpn.begin(); c != that.iv_cols_rpn.end(); ++c) + { + for(RPN_LIST::iterator r = c->begin(); r != c->end(); ++r) + { + r2.append(*r); + } + } + rpn1 = r1.listing("",iv_spy_names.front(),false); + rpn2 = r2.listing("",iv_spy_names.front(),false); + if(rpn1 != rpn2) + { + result = false; + oss << "this row/col rpn:" << endl; + oss << rpn1 << endl; + oss << "that row/col rpn:" << endl; + oss << rpn2 << endl; + } + + if(!result) cout << oss.str(); +#endif + return result; +} + + +//================================================================================================= +// SpyList Class definitions +//================================================================================================= + +ScomList::ScomList(const string & initfile, FILELIST & defines, ostream & stats, uint32_t i_ec) + : + iv_syntax_version(0), + iv_symbols(new Symbols(defines)), + iv_stats(stats), + iv_ec(i_ec) + +{ + yyscomlist = this; + + // What type of input? text(*.initfile) or binary(*.if) ? + size_t pos = initfile.rfind('.'); + string type; + if(pos != string::npos) + { + type = initfile.substr(pos+1); + } + + if(type.compare(0,8,"initfile") == 0) // source is text *.initfile + { + char line[100]; + string first_line; + yyin = fopen(initfile.c_str(), "r"); + if(!yyin) + { + string ers("ERROR: Could not open initfile: "); + ers.append(initfile); + throw invalid_argument(ers); + } + + // In Syntax version 1 the first or second line contains the CVS version + fgets(line,100,yyin); + first_line = line; + fgets(line,100,yyin); + first_line.append(line); + yyline = 3; + + dbg << "======================= Begin Parse ========================" << endl; + yyparse(); // Parse the initfile + dbg << "======================= End Parse ==========================" << endl; + + if(iv_syntax_version == 1) + { + // example pattern ..... $Id: galaxy.initfile,v 5.0 ...... + size_t pos = first_line.find("$Id:"); + if(pos != string::npos) + { + istringstream iss(first_line.substr(pos+4)); + string tok; + iss >> tok; // ex. galaxy.initfile,v + iss >> tok; // ex. 5.0 + iv_cvs_versions = tok; // just want the version number - eg '5.0' + } + } + + iv_stats << '*' << setw(20) << "lines:" << setw(6) << yyline-1 << endl; + iv_stats << '*' << setw(20) << "Scom statements:" << setw(6) << iv_scom_list.size() << endl; + // TODO num var/lits num lits found + } + else if(type.compare(0,2,"if") == 0) // source is binary *.if file + { +// TODO - No support for this currently +#if 0 + dbg << "======================= Begin Uncompiling ========================" << endl; + + BINSEQ bin_seq; + ifstream ifs(initfile.c_str(), ios_base::in | ios_base::binary); + if(!ifs) + { + string msg("ERROR: SpyList::Could not open "); + msg.append(initfile); + throw invalid_argument(msg); + } + while(1) + { + int ch = ifs.get(); + if (!(ifs.good())) break; + bin_seq.push_back(ch); + } + ifs.close(); + + // Turn this back into a list of spies + BINSEQ::const_iterator bli = bin_seq.begin(); + BINSEQ::const_iterator b; + + iv_syntax_version = Rpn::extract32(bli); + bli += 8; + if(iv_syntax_version == 1) + { + for(b = bli-8; (b != bli) && (*b); ++b) + { + iv_cvs_versions.push_back(*b); + } + } + else + { + // offset to CVS sub version section + b = bin_seq.begin() + Rpn::extract32(bli); + size_t size = Rpn::extract16(b); + while(size--) iv_cvs_versions.push_back(*b++); + } + + b = bin_seq.begin() + Rpn::extract32(bli); + iv_symbols->restore_var_bseq(b); + + b = bin_seq.begin() + Rpn::extract32(bli); + iv_symbols->restore_lit_bseq(b); + + size_t section_count = Rpn::extract32(bli); + if(section_count > LAST_WHEN_TYPE) + { + throw range_error("ERROR: SpyList::SpyList - Inalid # of sections"); + } + + for(size_t i = 0; i < section_count; ++i) + { + size_t spy_type = Rpn::extract32(bli); // type + size_t offset = Rpn::extract32(bli); // offset + size_t count = Rpn::extract32(bli); // Number of spies + + b = bin_seq.begin() + offset; + if(!(b < bin_seq.end())) + { + throw overflow_error("ERROR: SpyList::SpyList - iterator overflowed sequence"); + } + if(spy_type > LAST_WHEN_TYPE || spy_type == 0) + { + throw range_error("ERROR: SpyList::SpyList - when= type out of range"); + } + while(count--) + { + Scom * s = new Scom(b,iv_symbols); + insert(s); + s->set_when((SPY_WHEN)spy_type); + } + } +#endif + dbg << "======================= End Uncompiling ========================" << endl; + } + else + { + ostringstream ess; + ess << "ERROR: SpyList::SpyList Invalid file type: " << type; + ess << "\n source: " << initfile; + throw invalid_argument(ess.str()); + } +} + +//------------------------------------------------------------------------------------------------- + +ScomList::~ScomList() +{ + delete iv_symbols; +} + +//------------------------------------------------------------------------------------------------- + +void ScomList::clear() +{ + for(SCOM_LIST::iterator i = iv_scom_list.begin(); i != iv_scom_list.end(); ++i) delete i->second; + iv_scom_list.clear(); +} + +//------------------------------------------------------------------------------------------------- + +void ScomList::set_syntax_version(uint32_t v) +{ + if(v != 1 && v != 2) yyerror("Invalid Syntax Version"); + iv_syntax_version = v; +} + +//------------------------------------------------------------------------------------------------- + +void ScomList::compile(BINSEQ & bin_seq) +{ + uint32_t count_s = 0; + uint32_t section_count = 0; + size_t offset = 0; + + + BINSEQ blist_v; // vars + BINSEQ blist_i; // lits + BINSEQ blist_l; // when=L spies + BINSEQ blist_s; // when=S spies + BINSEQ blist_c; // when=C spies + BINSEQ blist_d; // when=D spies + + // Make the BINSEQs big enough to hopefully never have to resize + blist_v.reserve(0x00400); + blist_i.reserve(0x02000); + blist_l.reserve(0x30000); + blist_s.reserve(0x03000); + blist_c.reserve(0x03000); + blist_d.reserve(0x03000); + + + dbg << "======================== Begin compile ============================" << endl; + Rpn::set32(bin_seq,iv_syntax_version); // bytes[0:3] + + // bytes [4:12] + if(iv_syntax_version == 2) + { + const char * s = "SEE SUBV"; + for(; *s != 0; ++s) bin_seq.push_back(*s); + istringstream iss(iv_cvs_versions); + string vers; + while(iss >> vers) + { + stats << '*' << setw(20) << "Version:" << " " << vers << endl; + } + } + else if (iv_syntax_version == 1) + { + if(iv_cvs_versions.size()) + { + size_t len = iv_cvs_versions.size(); + if(len > 8) { iv_cvs_versions.erase(9); len = 8; } + for(string::const_iterator s = iv_cvs_versions.begin(); + s != iv_cvs_versions.end(); ++s) + { + bin_seq.push_back(*s); + } + while(len < 8) { bin_seq.push_back(0); ++len; } + stats << '*' << setw(20) << "Version:" << setw(6) << iv_cvs_versions << endl; + } + else + { + throw range_error("ERROR: No CVS version(s) specified"); + } + } + else // syntax version already validated to be 1 or 2 - so if we get here it was never set. + { + throw range_error("ERROR: No sytax version specified!"); + } + stats << '*' << setw(20) << "Syntax Version:" << setw(6) << iv_syntax_version << endl; + + + // Determine the number of scoms in each section + + for(SCOM_LIST::iterator i = iv_scom_list.begin(); i != iv_scom_list.end(); ++i) + { + // Filter out filtered spies dg003a + if(!(i->second->valid_when(dbg,iv_ec))) + { + continue; + } + + count_s += i->second->bin_listing(blist_s); + + } + if(count_s) ++section_count; + + // 28 bytes of File Header Data + offset = 28; + stats << '*' << setw(20) << "Sections:" << setw(6) << section_count << endl; + + // for verion 2 add offset to CVS versions section + if(iv_syntax_version == 2) + { + offset += 4; + Rpn::set32(bin_seq,offset); + offset += iv_cvs_versions.length() + 2; + } + // offset now points to start of Var Symbol Table + + iv_symbols->bin_vars(blist_v); // get Var table + iv_symbols->bin_lits(blist_i); // Get Lit table + + Rpn::set32(bin_seq,offset); // Offset to Variable Symbol Table + offset += blist_v.size(); // offset += var table byte size + Rpn::set32(bin_seq,offset); // Offset to Literal Symbol Table + offset += blist_i.size(); // offset += lit table byte size + + if(count_s) + { + Rpn::set32(bin_seq,offset); // SCOM Section offset + Rpn::set32(bin_seq,count_s); // Number of SCOM's + } + + if(iv_syntax_version == 2) // Add Sub-version section + { + Rpn::set16(bin_seq,(uint16_t)iv_cvs_versions.length()); // Length of Sub version + bin_seq.insert(bin_seq.end(), iv_cvs_versions.begin(), iv_cvs_versions.end()); + } + + bin_seq.insert(bin_seq.end(), blist_v.begin(), blist_v.end()); // add var table section + bin_seq.insert(bin_seq.end(), blist_i.begin(), blist_i.end()); // add lit table section + + if(count_s) + { + bin_seq.insert(bin_seq.end(), blist_s.begin(), blist_s.end()); // add SCOM section + stats << '*' << setw(20) << "S scoms:" << setw(6) << count_s << endl; + } + dbg << "======================== End compile ============================" << endl; +} + +//------------------------------------------------------------------------------------------------- + +bool Scom::valid_when(ostream & msg, uint32_t i_ec) //dg002a dg003c +{ + bool result = true; + + // unconditional state was determined earlier + if( iv_when_rpn.isTrue()) // unconditionally true - Rpn is not needed. + iv_when_rpn.clear(); + else if( iv_when_rpn.isFalse()) //unconditionally false + result = false; + else if(i_ec != 0xffffffff) + { + if(iv_when_rpn.resolve_ec(i_ec) == false) result = false; + } +#if 0 + if(result == false) + { + msg << hex; + SPY_NAMES::iterator i = iv_spy_names.begin(); + // if more than one spyname, the first is just the stem of the name - skip it + if(iv_spy_names.size() > 1) ++i; + + for(; i != iv_spy_names.end(); ++i) + { + if(i_ec != 0xffffffff) + msg << "For EC " << i_ec << ": "; + + msg << "Removing spy " << *i << endl; + } + msg << iv_when_rpn.listing("WHEN RPN","",true) << endl; + } +#endif + return result; +} + +//------------------------------------------------------------------------------------------------- + +void ScomList::listing(BINSEQ & bin_seq,ostream & olist) +{ + dbg << "======================= Begin Listing ========================" << endl; + + BINSEQ::const_iterator bli = bin_seq.begin(); + BINSEQ::const_iterator b; + uint32_t syntax_version = Rpn::extract32(bli); + + string cvs_versions; + + olist << hex << setfill('0'); + olist << "--------------- FILE HEADER ------------------------\n\n"; + olist << fmt8(syntax_version) << "[Syntax Version]\n" + << "0x"; + bli += 8; + for(b = bli-8; b != bli; ++b) olist << setw(2) << (uint32_t)(*b); + olist << " ["; + for(b = bli-8; b != bli; ++b) if((*b) != 0) olist << (char)(*b); + olist << "]\t[CVS Version]\n"; + if(syntax_version == 2) + { + size_t offset = Rpn::extract32(bli); + olist << fmt8(offset) << "[Offset to Sub-Version Section]\n"; + } + + uint32_t var_table_offset = Rpn::extract32(bli); + uint32_t lit_table_offset = Rpn::extract32(bli); + + olist << fmt8(var_table_offset) << "[Offset to Attribute Symbol Table]\n"; + olist << fmt8(lit_table_offset) << "[Offset to Literal Symbol Table]\n"; + + + b = bin_seq.begin() + var_table_offset; + iv_symbols->restore_var_bseq(b); + + b = bin_seq.begin() + lit_table_offset; + iv_symbols->restore_lit_bseq(b); + + b = bli; // save + + size_t offset = Rpn::extract32(bli); // offset + size_t count = Rpn::extract32(bli); // Number of spies + + olist << fmt8(offset) << "[Scom Section Offset]\n"; + olist << fmt8(count) << "[Number of scoms]\n"; + + olist << endl; + + if(syntax_version == 2) + { + olist << "--------------- Sub Version Section ---------------\n\n"; + uint16_t len = Rpn::extract16(bli); + olist << "0x" << setw(4) << len << "\t\t" + << "Length of Sub Version Section\n\n"; + for(uint16_t i = 0; i < len; ++i) olist << (char)(*bli++); + olist << endl; + } + + olist << iv_symbols->listing() << endl; + olist << "------------------- SCOM TABLES ------------------------\n\n" + << endl; + + bli = b; // restore + + olist << "------------ Scoms -----------\n\n"; + + b = bin_seq.begin() + offset; + if(!(b < bin_seq.end())) + { + throw overflow_error("ERROR: ScomList::listing - iterator overflowed sequence"); + } + while(count--) + { + Scom s(b,iv_symbols); + olist << s.listing() << endl; + } + + dbg << "======================= End Listing ========================" << endl; +} + +//------------------------------------------------------------------------------------------------- + +void ScomList::attr_listing(BINSEQ & bin_seq,ostream & olist) +{ + olist << iv_symbols->attr_listing(); +} + +//------------------------------------------------------------------------------------------------- + +string ScomList::fmt8(uint32_t val) +{ + ostringstream oss; + oss << setfill('0'); + oss << "0x" << hex << setw(8) << val << "\t " << '[' << dec << val << ']' << '\t'; + if(val < 1000) oss << '\t'; + return oss.str(); +} + + +//------------------------------------------------------------------------------------------------- + +void ScomList::insert(Scom * i_scom) +{ + uint64_t l_addr = i_scom->get_address(); + SCOM_LIST::iterator i = iv_scom_list.find(l_addr); + if(i == iv_scom_list.end()) + { + iv_scom_list[l_addr] = i_scom; + } + else + { + ostringstream oss; + oss << "Duplicate scom statement found on line " << i_scom->get_line() << endl; + oss << "First instance found on line " << i->second->get_line() << "Address: " << i_scom->get_address() << endl; + yyerror(oss.str().c_str()); + } +} + +//------------------------------------------------------------------------------------------------- + +bool ScomList::compare(ScomList & that) +{ + bool result = true; + dbg << "======================= Begin Compare ========================" << endl; + if(iv_scom_list.size() != that.iv_scom_list.size()) + { + cout << "E> Lists are not the same size" << endl; + result = false; + } + + // check each spy section + for(SCOM_LIST::iterator i = iv_scom_list.begin(); i != iv_scom_list.end(); ++i) + { + // The name checks spyname, arrayaddr (if array), bitrange(s) (if any) + uint64_t l_addr = i->second->get_address(); + SCOM_LIST::iterator j = that.iv_scom_list.find(l_addr); + if(j == that.iv_scom_list.end()) + { + cout << "E> " << l_addr << " not found in both lists!" << endl; + result = false; + continue; + } + if(i->second->compare(*(j->second)) == false) + { + cout << "E> Spy: " << l_addr << " does not match!" << endl; + result = false; + } + } + + // check for spies in that that are not in this + for(SCOM_LIST::iterator i = that.iv_scom_list.begin(); i != that.iv_scom_list.end(); ++i) + { + uint64_t l_addr = i->second->get_address(); + SCOM_LIST::iterator j = iv_scom_list.find(l_addr); + if(j == iv_scom_list.end()) + { + cout << "E> " << l_addr << " not found in both lists!" << endl; + result = false; + } + } + dbg << "======================= End Compare ========================" << endl; + return result; +} + +//------------------------------------------------------------------------------------------------- + +//------------------------------------------------------------------------------------------------- + +void Scom::set_scom_address(const string & i_scom_addr) +{ + + if(iv_scom_addr.size()) + { + yyerror("SCOM Address already set!"); + } + else + { + iv_scom_addr.push_back(i_scom_addr); + // cout << "I>Scom::set_scom_address: " << i_scom_addr << " is the output string!" << endl; + } +} + +//------------------------------------------------------------------------------------------------- + + +void Scom::dup_scom_address(const string & i_scom_addr) +{ + + + if(iv_scom_addr.size()) + { + iv_scom_addr.push_back(iv_scom_addr.front() + i_scom_addr); + } + else + yyerror("No base scom address to dulicate for append!"); + + // cout << "I>Scom::dup_scom_address: "<< i_scom_addr << " is the output string!" << endl; +} + +//------------------------------------------------------------------------------------------------- + +void Scom::set_scom_suffix(const string & i_scom_addr) +{ + + if(iv_scom_addr.size() == 1) iv_scom_addr[0] = iv_scom_addr[0] + i_scom_addr; + else if(iv_scom_addr.size() > 1) + { + SCOM_ADDR::iterator i = iv_scom_addr.begin(); + ++i; + for(;i != iv_scom_addr.end(); ++i) + { + *i += i_scom_addr; + } + } + else + yyerror("No base scom address to append suffix"); + + // cout << "I>Scom::set_scom_suffix: "<< i_scom_addr << " is the output string!" << endl; +} |