void prim_conv11::operator()
  (
   signal_& quality__io,
   signal_& wiregroup__io,
   signal_& hstrip__io,
   signal_& clctpat__io,
   signal_& ph__io,
   signal_& th__io,
   signal_& vl__io,
   signal_& phzvl__io,
   signal_& me11a__io,
   signal_& clctpat_r__io,
   signal_& ph_hit__io,
   signal_& th_hit__io,
   signal_& sel__io,
   signal_& addr__io,
   signal_& r_in__io,
   signal_& r_out__io,
   signal_& we__io,
   signal_& clk__io,
   signal_& control_clk__io
   )
{
  if (!built)
    {
      seg_ch = 2;
      bw_ph = 8;
      bw_th = 7;
      bw_fph = 12;
      bw_fth = 8;
      bw_wg = 7;
      bw_ds = 7;
      bw_hs = 8;
      pat_w_st3 = 3;
      pat_w_st1 = pat_w_st3 + 1;
      full_pat_w_st3 = (1 << (pat_w_st3+1)) - 1;
      full_pat_w_st1 = (1 << (pat_w_st1+1)) - 1;
      padding_w_st1 = full_pat_w_st1 / 2;
      padding_w_st3 = full_pat_w_st3 / 2;
      red_pat_w_st3 = pat_w_st3 * 2 + 1;
      red_pat_w_st1 = pat_w_st1 * 2 + 1;
      fold = 4;
      th_ch11 = seg_ch*seg_ch;
      bw_q = 4;
      bw_addr = 7;
      ph_raw_w = (1 << pat_w_st3) * 15;
      th_raw_w = (1 << bw_th);
      max_drift = 3;
      bw_phi = 12;
      bw_eta = 7;
      ph_hit_w = 40+4;
      ph_hit_w20 = ph_hit_w;
      ph_hit_w10 = 20+4;
      th_hit_w = 56 + 8;
      endcap = 1;
      n_strips = (station <= 1 && cscid <= 2) ? 64 :
	(station <= 1 && cscid >= 6) ? 64 : 80;
      n_wg = (station <= 1 && cscid <= 3) ? 48  :
	(station <= 1 && cscid >= 6) ? 32  :
	(station == 2 && cscid <= 3) ? 112 :
	(station >= 3 && cscid <= 3) ? 96  : 64;
      th_coverage = (station <= 1 && cscid <= 2) ? 45  :
	(station <= 1 && cscid >= 6) ? 27  :
	(station <= 1 && cscid >= 3) ? 39  :
	(station == 2 && cscid <= 2) ? 43  :
	(station == 2 && cscid >= 3) ? 56  :
	(station == 3 && cscid <= 2) ? 34  :
	(station == 3 && cscid >= 3) ? 52  :
	(station == 4 && cscid <= 2) ? 28  :
	(station == 4 && cscid >= 3) ? 50  : 0;
      ph_coverage = (station <= 1 && cscid >= 6) ? 15 : //30 :
	(station >= 2 && cscid <= 2) ? 40 : 20;
      th_ch = (station <= 1 && cscid <= 2) ? (seg_ch*seg_ch) : seg_ch;
      ph_reverse = (endcap == 1 && station >= 3) ? 1 : 
	(endcap == 2 && station <  3) ? 1 : 0;
      th_mem_sz = (1 << bw_addr);
      th_corr_mem_sz = (1 << bw_addr);
      mult_bw = bw_fph + 11;
      ph_zone_bnd1 = (station <= 1 && cscid <= 2) ? 41 :
	(station == 2 && cscid <= 2) ? 41 :
	(station == 2 && cscid >  2) ? 87 :
	(station == 3 && cscid >  2) ? 49 :
	(station == 4 && cscid >  2) ? 49 : 127;
      ph_zone_bnd2 = (station == 3 && cscid >  2) ? 87 : 127;
      zone_overlap = 2;
      bwr = 6;
      bpow = 6;
      cnr = (1 << bpow);
      cnrex = ph_raw_w;
      build();
      // input parameters from MPC
      quality.attach(quality__io);
      wiregroup.attach(wiregroup__io);
      hstrip.attach(hstrip__io);
      clctpat.attach(clctpat__io);
      sel.attach(sel__io);
      addr.attach(addr__io);
      r_in.attach(r_in__io);
      we.attach(we__io);
      clk.attach(clk__io);
      control_clk.attach(control_clk__io);
      // outputs
      // low-precision ph, only for detection
      // high-precision ph with displacement correction will be calculated when 
      // 3 best tracks are found.
      ph.attach(ph__io);
      // full precision th, but without displacement correction, takes th duplication into account
      th.attach(th__io);
      // one-bit valid flags
      vl.attach(vl__io);
      phzvl.attach(phzvl__io);
      me11a.attach(me11a__io);
      clctpat_r.attach(clctpat_r__io);
      // ph and th raw hits
      ph_hit.attach(ph_hit__io);
      th_hit.attach(th_hit__io);
      r_out.attach(r_out__io);
    }

	
  pc_id(3,0) = cscid;
  pc_id(7,4) = station;
	
  r_out = (sel == const_(2, 0x0UL)) ? params[addr] : 
    (sel == const_(2, 0x1UL)) ? th_mem[addr] : 
    (sel == const_(2, 0x2UL)) ? th_corr_mem[addr] : pc_id;

  beginalways();	

  if (posedge (control_clk))
    {
      if (( (sel) == 0)) {  { if (we) params     [addr] = r_in; } } else 
	if (( (sel) == 1)) {  { if (we) th_mem     [addr] = r_in; } } else 
	  if (( (sel) == 2)) {  { if (we) th_corr_mem[addr] = r_in(3,0); } } 
    }
  endalways();

  beginalways();
	
  if (posedge (clk))
    {

      // zero outputs
      vl = 0;
      phzvl = 0;
      for (i = 0; i < seg_ch; i = i+1) { fph[i] = 0; clctpat_r[i] = 0; }
      for (i = 0; i < th_ch;  i = i+1) th[i] = 0;
      ph_hit = 0;
      th_hit = 0;

      for (i = 0; i < seg_ch; i = i+1)
	{

	  factor[i] = (station <= 1 && cscid <= 2 && hstrip[i] > 127) ? 1707 : // ME1/1a
	    1301; // ME1/1b
				 
	  //if(factor[i])
	  //	std::cout<<"factor 11 = "<<factor[i]<<std::endl;

	  me11a_w[i] = (station <= 1 && cscid <= 2 && hstrip[i] > 127);
	  if (( (clctpat[i]) == 0)) {  { clct_pat_corr = const_(3, 0x0UL); clct_pat_sign = 0; } } else 
	    if (( (clctpat[i]) == 1)) {  { clct_pat_corr = const_(3, 0x0UL); clct_pat_sign = 0; } } else 
	      if (( (clctpat[i]) == 2)) {  { clct_pat_corr = const_(3, 0x5UL); clct_pat_sign = 1; } } else 
		if (( (clctpat[i]) == 3)) {  { clct_pat_corr = const_(3, 0x5UL); clct_pat_sign = 0; } } else 
		  if (( (clctpat[i]) == 4)) {  { clct_pat_corr = const_(3, 0x5UL); clct_pat_sign = 1; } } else 
		    if (( (clctpat[i]) == 5)) {  { clct_pat_corr = const_(3, 0x5UL); clct_pat_sign = 0; } } else 
		      if (( (clctpat[i]) == 6)) {  { clct_pat_corr = const_(3, 0x2UL); clct_pat_sign = 1; } } else 
			if (( (clctpat[i]) == 7)) {  { clct_pat_corr = const_(3, 0x2UL); clct_pat_sign = 0; } } else 
			  if (( (clctpat[i]) == 8)) {  { clct_pat_corr = const_(3, 0x2UL); clct_pat_sign = 1; } } else 
			    if (( (clctpat[i]) == 9)) {  { clct_pat_corr = const_(3, 0x2UL); clct_pat_sign = 0; } } else 
			      if (( (clctpat[i]) == 10)) {  { clct_pat_corr = const_(3, 0x0UL); clct_pat_sign = 0; } } else  {  { clct_pat_corr = const_(3, 0x0UL); clct_pat_sign = 0; } } 

	  // reverse clct pattern correction if chamber is reversed
	  //			if (ph_reverse) clct_pat_sign = ~clct_pat_sign;

	  // convert into 1/8 strips and remove ME1/1a offset (512=128*4)
	  eight_str[i]  = (const_s(2, 0x0UL), hstrip [i], const_s(2, 0x0UL)) - (me11a_w[i] ? 512 : 0);
			
	  // clct pattern correction
	  if (clct_pat_sign == 0) eight_str[i] = eight_str[i] + clct_pat_corr(2,1);
	  else eight_str[i] = eight_str[i] - clct_pat_corr(2,1);

	  if (quality[i])
	    {
	      vl[i] = 1;
	      // ph conversion
	      // for factors 1024 and 2048 the multiplier should be replaced with shifts by synthesizer
	      mult = eight_str[i] * factor[i];
	      ph_tmp = mult(mult_bw-1 , 10);
	      //std::cout<<"ph_tmp = "<<ph_tmp<<std::endl;
	      ph_init_ix =  me11a_w[i] ? const_(3, 2UL) : const_(3, 0UL); // index of ph_init parameter to apply (different for ME11a and b)
	      //std::cout<<"ph_init_ix = "<<ph_init_ix<<std::endl;
	      if (ph_reverse)
		{
		  fph[i] = params[ph_init_ix] - ph_tmp;
		  // set ph raw hits
		  ph_hit[ph_coverage - ph_tmp(bw_fph-1,5) + params[ph_init_ix + const_(3, 1UL)](7,1)] = 1;
		}
	      else
		{            
		  fph[i] = params[ph_init_ix] + ph_tmp;
		  // set ph raw hits
		  ph_hit[ph_tmp(bw_fph-1,5) + params[ph_init_ix + const_(3, 1UL)](7,1)] = 1;
		  /* -----\/----- EXCLUDED -----\/-----
		  // add hits to take ME11a strip ganging into account
		  // offsets of 14 and 28 is what I observe from MC. Calculations show 11.6 and 23.2 (???)
		  if (me11a_w[i])
		  {
		  ph_hit[ph_tmp(bw_fph-1,5) + params[2] + 14] = 1;
		  ph_hit[ph_tmp(bw_fph-1,5) + params[2] + 28] = 1;
		  }
		  -----/\----- EXCLUDED -----/\----- */
		}
				
	      //std::cout<<"estr = "<<eight_str[i]<<", factor = "<<factor[i]<<", ph_rev = "<<ph_reverse<<", ph_tmp = "<<ph_tmp<<std::endl;
	      //std::cout<<"ph_hit = "<<ph_tmp(bw_fph-1,5) + params[ph_init_ix + const_(3, 1UL)](7,1)<<std::endl;
	      //std::cout<<"strip = "<<hstrip[i]<<", Id = "<<cscid + 1<<",phinit = "<<(params[ph_init_ix])<<"ph_cov = "<<ph_coverage<<", and phshift = "<<(ph_tmp(bw_fph-1,5))<<", and phdisp = "<<(params[ph_init_ix + const_(3, 1UL)](7,1))<<"\n\n\n";
				
				
	      wg = wiregroup[i];
	      // th conversion
	      // call appropriate LUT, it returns th[i] relative to wg0 of that chamber
	      th_orig = th_mem[wg];
	      //std::cout<<"wire = "<<wg<<", th_mem[wg] = "<<th_orig<<std::endl;


	      // need th duplication here
	      for (j = 0; j < seg_ch; j = j+1)
		{
		  if (quality[j])
		    {
		      // calculate correction for each strip number
		      // index is: (wiregroup(2 MS bits), dblstrip(5-bit for these chambers))
		      index = (wg(5,4), eight_str[j](8,4));
		      th_corr = th_corr_mem[index];
		      //std::cout<<"eightstrip = "<<eight_str[j]<<", eightstrip(8,4) = "<<eight_str[j](8,4)<<", index = "<<index<<", th_corr = "<<th_corr<<std::endl;

		      //std::cout<<"th_corr = "<<th_corr<<" and th_orig = "<<th_orig<<std::endl;
		      // apply correction to the corresponding output
		      if (ph_reverse) th_tmp = (th_orig - th_corr) & const_(6, 0x3fUL);
		      else            th_tmp = (th_orig + th_corr) & const_(6, 0x3fUL);
		      //std::cout<<"ph_reverse = "<<ph_reverse<<" ";
		      //if(th_tmp)std::cout<<"th_tmp = "<<th_tmp<<" and thcoverage = "<<th_coverage<<std::endl;
		      // check that correction did not make invalid value outside chamber coverage
		      // this will actually take care of both positive and negative illegal values
		      if (th_tmp < th_coverage) 
			{
			  // apply initial th value for that chamber
			  th[i*seg_ch+j] = th_tmp + params[4];
			  //std::cout<<"params[4] = "<<params[4]<<"\n";
							
			  // th hits
			  th_hit[th_tmp + params[5]] = 1;
							
							
			  // check which zones ph hits should be applied to
			  if (th[i*seg_ch+j] <= (ph_zone_bnd1 + zone_overlap)) phzvl[0] = 1;
			  if (th[i*seg_ch+j] >  (ph_zone_bnd2 - zone_overlap)) phzvl[2] = 1;
			  if (
			      (th[i*seg_ch+j] >  (ph_zone_bnd1 - zone_overlap)) &&
			      (th[i*seg_ch+j] <= (ph_zone_bnd2 + zone_overlap))
			      ) phzvl[1] = 1;
			  //std::cout<<"ph_zone_bnd1 = "<<ph_zone_bnd1<<std::endl;
			  //std::cout<<"phzvl = "<<phzvl<<std::endl;
			}
		    }
		}
	      clctpat_r[i] = clctpat[i]; // just propagate pattern downstream
	    } // if (quality[i])
			
	  ph[i] = fph[i];
	  //if(fph[i]) std::cout<<"fph["<<i<<"] = "<<fph[i]<<" and vl[i] = "<<vl[i]<<std::endl;
			
	} // for (i = 0; i < seg_ch; i = i+1)
      me11a = me11a_w;
    }
  endalways();
}
Beispiel #2
0
void Writer::CreatePCEntry(Schema const& buffer_schema)
{


    boost::uint32_t precision = getDefaultedOption<boost::uint32_t>("stream_output_precision");
    boost::uint32_t capacity = getDefaultedOption<boost::uint32_t>("capacity");




    std::ostringstream oss;


    oss.setf(std::ios_base::fixed, std::ios_base::floatfield);
    oss.precision(precision);

    std::ostringstream columns;
    std::ostringstream values;

    if (!m_base_table_aux_columns.empty())
    {
        columns << m_cloud_column_name << "," << m_base_table_aux_columns;

        values << "pc," << m_base_table_aux_values;
    }
    else
    {
        columns << m_cloud_column_name;
        values << "pc";
    }

    int nPCPos = 1;
    int nSchemaPos = 1;
    nSchemaPos++;

    int nPos = nSchemaPos; // Bind column position

    if (!m_base_table_boundary_column.empty())
    {
        columns << "," << m_base_table_boundary_column;
        nPos++;
        values <<", SDO_GEOMETRY(:"<<nPos;
        nPos++;
        values <<", :"<<nPos<<")";
    }



    std::ostringstream s_srid;
    std::ostringstream s_geom;
    std::ostringstream s_schema;


    // IsGeographic(srid);

    if (m_srid == 0)
    {
        s_srid << "NULL";
    }
    else
    {
        s_srid << m_srid;
    }

    s_schema << "xmltype(:"<<nSchemaPos<<")";



    std::string eleminfo = CreatePCElemInfo();

    pdal::Bounds<double> base_table_bounds = getDefaultedOption<pdal::Bounds<double> >("base_table_bounds");

    if (base_table_bounds.empty())
    {
        if (IsGeographic(m_srid))
        {
            base_table_bounds.setMinimum(0, -179.99);
            base_table_bounds.setMinimum(1, -89.99);
            base_table_bounds.setMinimum(2, 0.0);
            base_table_bounds.setMaximum(0, 179.99);
            base_table_bounds.setMaximum(1, 89.99);
            base_table_bounds.setMaximum(2, 20000.0);
        }
        else
        {
            base_table_bounds.setMinimum(0, 0.0);
            base_table_bounds.setMinimum(1, 0.0);
            base_table_bounds.setMinimum(2, 0.0);
            base_table_bounds.setMaximum(0, 100.0);
            base_table_bounds.setMaximum(1, 100.0);
            base_table_bounds.setMaximum(2, 20000.0);
        }
    }
    s_geom << "           mdsys.sdo_geometry("<< m_gtype <<", "<<s_srid.str()<<", null,\n"
           "              mdsys.sdo_elem_info_array"<< eleminfo <<",\n"
           "              mdsys.sdo_ordinate_array(\n";

    s_geom << base_table_bounds.getMinimum(0) << "," << base_table_bounds.getMinimum(1) << ",";

    if (m_is3d)
    {
        s_geom << base_table_bounds.getMinimum(2) << ",";
    }

    s_geom << base_table_bounds.getMaximum(0) << "," << base_table_bounds.getMaximum(1);

    if (m_is3d)
    {
        s_geom << "," << base_table_bounds.getMaximum(2);
    }

    s_geom << "))";

    boost::uint32_t dimensions = 8;

    oss << "declare\n"
        "  pc_id NUMBER := :"<<nPCPos<<";\n"
        "  pc sdo_pc;\n"

        "begin\n"
        "  -- Initialize the Point Cloud object.\n"
        "  pc := sdo_pc_pkg.init( \n"
        "          '"<< m_base_table_name<<"', -- Table that has the SDO_POINT_CLOUD column defined\n"
        "          '"<< m_cloud_column_name<<"',   -- Column name of the SDO_POINT_CLOUD object\n"
        "          '"<< m_block_table_name <<"', -- Table to store blocks of the point cloud\n"
        "           'blk_capacity="<< capacity <<"', -- max # of points per block\n"
        << s_geom.str() <<
        ",  -- Extent\n"
        "     0.5, -- Tolerance for point cloud\n"
        "           "<<dimensions<<", -- Total number of dimensions\n"
        "           NULL,"
        "            NULL,"
        "            "<< s_schema.str() <<");\n"
        "  :"<<nPCPos<<" := pc.pc_id;\n"

        "  -- Insert the Point Cloud object  into the \"base\" table.\n"
        "  insert into " << m_base_table_name << " ( ID, "<< columns.str() <<
        ") values ( pc.pc_id, " << values.str() << ");\n"

        "  "
        "end;\n";

    Statement statement = Statement(m_connection->CreateStatement(oss.str().c_str()));

    statement->Bind(&m_pc_id);


    OCILobLocator* schema_locator ;
    OCILobLocator* boundary_locator ;

    std::string schema_data;

    bool pack = getOptions().getValueOrDefault<bool>("pack_ignored_fields", true);
    if (pack)
    {
        schema::index_by_index const& idx = buffer_schema.getDimensions().get<schema::index>();
        log()->get(logDEBUG3) << "Packing ignored dimension from PointBuffer " << std::endl;

        boost::uint32_t position(0);
        
        pdal::Schema clean_schema;
        schema::index_by_index::size_type i(0);
        for (i = 0; i < idx.size(); ++i)
        {
            if (! idx[i].isIgnored())
            {
                
                Dimension d(idx[i]);
                d.setPosition(position);
                
                // Wipe off parent/child relationships if we're ignoring 
                // same-named dimensions
                d.setParent(boost::uuids::nil_uuid());
                clean_schema.appendDimension(d);
                position++;
            }
        }
        schema_data = pdal::Schema::to_xml(clean_schema);
            
    } else
    {
        schema_data = pdal::Schema::to_xml(buffer_schema);
        
    }

    char* schema = (char*) malloc(schema_data.size() * sizeof(char) + 1);
    strncpy(schema, schema_data.c_str(), schema_data.size());
    schema[schema_data.size()] = '\0';
    statement->WriteCLob(&schema_locator, schema);
    statement->Bind(&schema_locator);

    std::ostringstream wkt_s;

    if (!m_base_table_boundary_column.empty())
    {
        if (!FileUtils::fileExists(m_base_table_boundary_wkt))
        {
            if (!IsValidWKT(m_base_table_boundary_wkt))
            {
                std::ostringstream oss;
                oss << "WKT for base_table_boundary_wkt was not valid and '" << m_base_table_boundary_wkt
                    << "' doesn't exist as a file";
                throw pdal::pdal_error(oss.str());
            }
            wkt_s << m_base_table_boundary_wkt;
        }
        else
        {
            std::string wkt = LoadSQLData(m_base_table_boundary_wkt);
            if (!IsValidWKT(wkt))
            {
                std::ostringstream oss;
                oss << "WKT for base_table_boundary_wkt was from file '" << m_base_table_boundary_wkt
                    << "' is not valid";
                throw pdal::pdal_error(oss.str());
            }
            wkt_s << wkt;
        }
    }

    std::string wkt_string = wkt_s.str();
    char* wkt = (char*) malloc(wkt_string.size() * sizeof(char)+1);
    strncpy(wkt, wkt_string.c_str(), wkt_string.size());
    wkt[wkt_string.size()] = '\0';
    if (!m_base_table_boundary_column.empty())
    {
        statement->WriteCLob(&boundary_locator, wkt);
        statement->Bind(&boundary_locator);
        statement->Bind((int*)&m_srid);

    }

    try
    {
        statement->Execute();
    }
    catch (std::runtime_error const& e)
    {
        std::ostringstream oss;
        oss << "Failed at creating Point Cloud entry into " << m_base_table_name << " table. Does the table exist? "  << e.what();
        throw pdal_error(oss.str());
    }

    free(wkt);

    try
    {
        Option& pc_id = getOptions().getOptionByRef("pc_id");
        pc_id.setValue(m_pc_id);
    }
    catch (pdal::option_not_found&)
    {
        Option pc_id("pc_id", m_pc_id, "Point Cloud Id");
        getOptions().add(pc_id);
    }

}
Beispiel #3
0
void Writer::CreateCloud(Schema const& buffer_schema)
{
    std::string cloud_table = getOptions().getValueOrThrow<std::string>("cloud_table");
    std::string block_table = getOptions().getValueOrThrow<std::string>("block_table");

    std::ostringstream oss;

    pdal::Schema output_schema(buffer_schema);
    bool pack = getOptions().getValueOrDefault<bool>("pack_ignored_fields", true);
    if (pack)
    {
        output_schema = getPackedSchema(buffer_schema);
    }

    std::string bounds = getOptions().getValueOrDefault<std::string>("cloud_boundary_wkt", "");
    if (bounds.size())
    {
        log()->get(logDEBUG2) << "have cloud_boundary_wkt of size " << bounds.size() << std::endl;
        bounds = loadGeometryWKT(bounds);

    }


        std::string cloud_column = getOptions().getValueOrDefault<std::string>("cloud_column", "id");
        oss << "INSERT INTO " << boost::to_lower_copy(cloud_table)
            << "(" 
            << " block_table, schema) VALUES ('"
            << boost::to_lower_copy(block_table)
            << "',:xml) ";
        std::string xml = pdal::Schema::to_xml(output_schema);
        m_session->once << oss.str(), ::soci::use(xml);
        oss.str("");


        long id;
        oss << "select last_insert_rowid()";
        m_session->once << oss.str(), ::soci::into(id);
        oss.str("");

        //
        // int id;
        // oss << "SELECT CURRVAL('"<< boost::to_lower_copy(cloud_table)  <<"_id_seq')";
        // (m_session->once << oss.str(), ::soci::into(id));
        // oss.str("");

        log()->get(logDEBUG) << "Point cloud id was " << id << std::endl;
        try
        {
            Option& pc_id = getOptions().getOptionByRef("pc_id");
            pc_id.setValue(id);
        }
        catch (pdal::option_not_found&)
        {
            Option pc_id("pc_id", id, "Point Cloud Id");
            getOptions().add(pc_id);
        }

        if (bounds.size())
        {
            boost::uint32_t srid = getOptions().getValueOrDefault<boost::uint32_t>("srid", 4326);
            bool is3d = getOptions().getValueOrDefault<bool>("is3d", false);
            std::string force =  "ST_Force_2D";

            oss << "UPDATE "
                << boost::to_lower_copy(cloud_table)
                << " SET extent="<< force
                << "(ST_GeometryFromText(:wkt,:srid)) where "
                << boost::to_lower_copy(cloud_column) <<"=:id";

            m_session->once << oss.str(), ::soci::use(bounds, "wkt"), ::soci::use(srid,"srid"), ::soci::use(id, "id");

        }
}
Beispiel #4
0
void prim_conv::operator()
(
	signal_& quality__io,
	signal_& wiregroup__io,
	signal_& hstrip__io,
	signal_& clctpat__io,
	signal_& ph__io,
	signal_& th__io,
	signal_& vl__io,
	signal_& phzvl__io,
	signal_& me11a__io,
	signal_& clctpat_r__io,
	signal_& ph_hit__io,
	signal_& th_hit__io,
	signal_& sel__io,
	signal_& addr__io,
	signal_& r_in__io,
	signal_& r_out__io,
	signal_& we__io,
	signal_& clk__io,
	signal_& control_clk__io
)
{
	if (!built)
	{
		seg_ch = 2;
		bw_ph = 8;
		bw_th = 7;
		bw_fph = 12;
		bw_fth = 8;
		bw_wg = 7;
		bw_ds = 7;
		bw_hs = 8;
		pat_w_st3 = 3;
		pat_w_st1 = pat_w_st3 + 1;
		full_pat_w_st3 = (1 << (pat_w_st3+1)) - 1;
		full_pat_w_st1 = (1 << (pat_w_st1+1)) - 1;
		padding_w_st1 = full_pat_w_st1 / 2;
		padding_w_st3 = full_pat_w_st3 / 2;
		red_pat_w_st3 = pat_w_st3 * 2 + 1;
		red_pat_w_st1 = pat_w_st1 * 2 + 1;
		fold = 4;
		th_ch11 = seg_ch*seg_ch;
		bw_q = 4;
		bw_addr = 7;
		ph_raw_w = (1 << pat_w_st3) * 15;
		th_raw_w = (1 << bw_th);
		max_drift = 3;
		bw_phi = 12;
		bw_eta = 7;
		ph_hit_w = 40+4;
		ph_hit_w20 = ph_hit_w;
		ph_hit_w10 = 20+4;
		th_hit_w = 56 + 8;
		endcap = 1;
		n_strips = (station <= 1 && cscid <= 2) ? 64 :
						 (station <= 1 && cscid >= 6) ? 64 : 80;
		n_wg = (station <= 1 && cscid <= 3) ? 48  :
					 (station <= 1 && cscid >= 6) ? 32  :
					 (station == 2 && cscid <= 3) ? 112 :
					 (station >= 3 && cscid <= 3) ? 96  : 64;
		th_coverage = (station <= 1 && cscid <= 2) ? 45  :
						 (station <= 1 && cscid >= 6) ? 27  :
						 (station <= 1 && cscid >= 3) ? 39  :
						 (station == 2 && cscid <= 2) ? 43  :
						 (station == 2 && cscid >= 3) ? 56  :
						 (station == 3 && cscid <= 2) ? 34  :
						 (station == 3 && cscid >= 3) ? 52  :
						 (station == 4 && cscid <= 2) ? 28  :
						 (station == 4 && cscid >= 3) ? 50  : 0;
		ph_coverage = (station <= 1 && cscid >= 6) ? 15 : //30 :
						   (station >= 2 && cscid <= 2) ? 40 : 20;
		th_ch = (station <= 1 && cscid <= 2) ? (seg_ch*seg_ch) : seg_ch;
		ph_reverse = (endcap == 1 && station >= 3) ? 1 : 
			   			   (endcap == 2 && station <  3) ? 1 : 0;
		th_mem_sz = (1 << bw_addr);
		th_corr_mem_sz = (1 << bw_addr);
		mult_bw = bw_fph + 11;
		ph_zone_bnd1 = (station <= 1 && cscid <= 2) ? 41 :
							(station == 2 && cscid <= 2) ? 41 :
							(station == 2 && cscid >  2) ? 87 :
							(station == 3 && cscid >  2) ? 49 :
							(station == 4 && cscid >  2) ? 49 : 127;
		ph_zone_bnd2 = (station == 3 && cscid >  2) ? 87 : 127;
		zone_overlap = 2;
		bwr = 6;
		bpow = 6;
		cnr = (1 << bpow);
		cnrex = ph_raw_w;
		build();
		// input parameters from MPC
		quality.attach(quality__io);
		wiregroup.attach(wiregroup__io);
		hstrip.attach(hstrip__io);
		clctpat.attach(clctpat__io);
		sel.attach(sel__io);
		addr.attach(addr__io);
		r_in.attach(r_in__io);
		we.attach(we__io);
		clk.attach(clk__io);
		control_clk.attach(control_clk__io);
		// outputs
// phi
		ph.attach(ph__io);
		// full precision th, but without displacement correction
		th.attach(th__io);
		// one-bit valid flags
		vl.attach(vl__io);
		phzvl.attach(phzvl__io);
		me11a.attach(me11a__io);
		clctpat_r.attach(clctpat_r__io);
		// ph and th raw hits
		ph_hit.attach(ph_hit__io);
		th_hit.attach(th_hit__io);
		r_out.attach(r_out__io);
	}


	 pc_id(3,0) = cscid;
	 pc_id(7,4) = station;
	


	// ME11 special case
	// all other stations
	 r_out = (sel == const_(2, 0x0UL)) ? params[addr] : 
				   (sel == const_(2, 0x1UL)) ? th_mem[addr] : pc_id;

	beginalways();	

	if (posedge (control_clk))
	{
		if (( (sel) == 0)) {  { if (we) params [addr] = r_in; } } else 
		if (( (sel) == 1)) {  { if (we) th_mem [addr] = r_in; } }  // case (sel)
	}
	endalways();

	beginalways();

	
	if (posedge (clk))
	{

		// zero outputs
		vl = 0;
		phzvl = 0;
		for (i = 0; i < seg_ch; i = i+1) { fph[i] = 0; th[i] = 0; clctpat_r[i] = 0; }
		ph_hit = 0;
		th_hit = 0;
		

		// strip width factor relative to ME234/2 
		// 1024 == 1
		factor = (station <= 1 && cscid >= 6) ? 947 : // ME1/3
				 1024; // all other chambers
				 
		//if(factor)
		//	std::cout<<"factor else = "<<factor<<std::endl;

		for (i = 0; i < seg_ch; i = i+1)
		{

			me11a_w[i] = 0;
			if (( (clctpat[i]) == 0)) {  { clct_pat_corr = const_(3, 0x0UL); clct_pat_sign = 0; } } else 
			if (( (clctpat[i]) == 1)) {  { clct_pat_corr = const_(3, 0x0UL); clct_pat_sign = 0; } } else 
			if (( (clctpat[i]) == 2)) {  { clct_pat_corr = const_(3, 0x5UL); clct_pat_sign = 1; } } else 
			if (( (clctpat[i]) == 3)) {  { clct_pat_corr = const_(3, 0x5UL); clct_pat_sign = 0; } } else 
			if (( (clctpat[i]) == 4)) {  { clct_pat_corr = const_(3, 0x5UL); clct_pat_sign = 1; } } else 
			if (( (clctpat[i]) == 5)) {  { clct_pat_corr = const_(3, 0x5UL); clct_pat_sign = 0; } } else 
			if (( (clctpat[i]) == 6)) {  { clct_pat_corr = const_(3, 0x2UL); clct_pat_sign = 1; } } else 
			if (( (clctpat[i]) == 7)) {  { clct_pat_corr = const_(3, 0x2UL); clct_pat_sign = 0; } } else 
			if (( (clctpat[i]) == 8)) {  { clct_pat_corr = const_(3, 0x2UL); clct_pat_sign = 1; } } else 
			if (( (clctpat[i]) == 9)) {  { clct_pat_corr = const_(3, 0x2UL); clct_pat_sign = 0; } } else 
			if (( (clctpat[i]) == 10)) {  { clct_pat_corr = const_(3, 0x0UL); clct_pat_sign = 0; } } else  {  { clct_pat_corr = const_(3, 0x0UL); clct_pat_sign = 0; } } 

			// reverse clct pattern correction if chamber is reversed
//			if (ph_reverse) clct_pat_sign = ~clct_pat_sign;
			
			// 10 deg chambers		
			if (station < 2 || cscid > 2)
			{
				eight_str[i]  = (const_s(2, 0x0UL), hstrip [i], const_s(2, 0x0UL)); // full precision, uses only 2 bits of clct pattern correction
				if (clct_pat_sign == 0) eight_str[i] = eight_str[i] + clct_pat_corr(2,1);
				else eight_str[i] = eight_str[i] - clct_pat_corr(2,1);
			}
			else
			{
				// 20 deg chambers
				eight_str[i]  = (const_s(1, 0x0UL), hstrip [i], const_s(3, 0x0UL)); // multiply by 2, uses all 3 bits of pattern correction
				if (clct_pat_sign == 0) eight_str[i] = eight_str[i] + clct_pat_corr;
				else eight_str[i] = eight_str[i] - clct_pat_corr;
			}
			
			
			if (quality[i])
			{
				vl[i] = 1;
				// ph conversion
				// for factors 1024 and 2048 the multiplier should be replaced with shifts by synthesizer
				mult = eight_str[i] * factor;
				ph_tmp = mult(mult_bw-1 , 10);
				if (ph_reverse)
				{
					fph[i] = params[0] - ph_tmp;
					// set ph raw hits
					ph_hit[ph_coverage - ph_tmp(bw_fph-1,5) + params[2](7,1)] = 1;
				}
				else
				{            
					fph[i] = params[0] + ph_tmp;
					// set ph raw hits
					ph_hit[ph_tmp(bw_fph-1,5) + params[2](7,1)] = 1;
				}
				
				if(fph[i])
					std::cout<<"fph["<<i<<"] = "<<fph[i]<<" and vl[i] = "<<vl[i]<<std::endl;
				//std::cout<<"estr = "<<eight_str[i]<<", factor = "<<factor<<", ph_rev = "<<ph_reverse<<", ph_tmp = "<<ph_tmp<<std::endl;
				//std::cout<<"strip = "<<hstrip[i]<<", Id = "<<cscid + 1<<",phinit = "<<params[0]<<"ph_cov = "<<ph_coverage<<", and phshift = "<<ph_tmp(bw_fph-1,5)<<", and params[2] = "<<params[2](7,1)<<"\n\n\n";
				wg = wiregroup[i];
				// th conversion
				th_tmp = th_mem[wg];
				th[i] = th_tmp + params[1];

				th_hit[th_tmp + params[3]] = 1;

				// check which zones ph hits should be applied to
				if (th[i] <= (ph_zone_bnd1 + zone_overlap)) phzvl[0] = 1;
				if (th[i] >  (ph_zone_bnd2 - zone_overlap)) phzvl[2] = 1;
				if (
					(th[i] >  (ph_zone_bnd1 - zone_overlap)) &&
					(th[i] <= (ph_zone_bnd2 + zone_overlap))
					) phzvl[1] = 1;

				clctpat_r[i] = clctpat[i]; // just propagate pattern downstream
				std::cout<<"phzvl = "<<phzvl<<std::endl;
			} // if (quality[i])

			ph[i] = fph[i];
		}
		me11a = 0;
	}
	endalways();
}